summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/picotls
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:57:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:57:58 +0000
commitbe1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch)
tree9754ff1ca740f6346cf8483ec915d4054bc5da2d /web/server/h2o/libh2o/deps/picotls
parentInitial commit. (diff)
downloadnetdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz
netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--web/server/h2o/libh2o/deps/picotls/.clang-format7
-rw-r--r--web/server/h2o/libh2o/deps/picotls/.gitignore24
-rw-r--r--web/server/h2o/libh2o/deps/picotls/.gitmodules3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/.travis.yml17
-rw-r--r--web/server/h2o/libh2o/deps/picotls/CMakeLists.txt51
-rw-r--r--web/server/h2o/libh2o/deps/picotls/README.md78
-rw-r--r--web/server/h2o/libh2o/deps/picotls/WindowsPort.md34
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/.travis.yml29
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/COPYING121
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/README.md246
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/curve25519-shootout.md16
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/Makefile3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/build.py274
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/conf.py263
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/index.rst33
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/.gitignore1
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/Makefile13
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/README.md2
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c60
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py38
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/.gitignore5
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/Makefile17
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c206
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl91
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl36
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl41
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl62
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl67
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl67
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/.gitignore15
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/Makefile54
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.c419
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.h152
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/.gitignore3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/Makefile184
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/analyse.py207
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/boot.c144
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt22
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h55
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld7
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld172
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/main.c447
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memcpy.s49
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memset.s50
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/merge.py26
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/report.py276
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.c170
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.h40
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.s15
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s199
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s176
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s1109
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c761
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s777
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/bitops.h310
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.c195
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.h147
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cbcmac.c79
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ccm.c193
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cf_config.h59
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c161
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c148
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.h73
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.c28
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.h137
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c150
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.c29
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.donna.c867
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.h42
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.naclref.c273
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c235
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.c434
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.h191
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/eax.c116
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/cutest.h620
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/handy.h66
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gcm.c249
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.c114
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.h55
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.c106
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.h78
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.c99
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.h587
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.c410
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.h84
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ocb.c404
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.c84
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.h47
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.c221
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.h91
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.py127
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/prp.h64
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.c164
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.h140
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.c150
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.h91
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha2.h235
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha256.c232
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.c444
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.h180
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha512.c248
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/tassert.h32
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testaes.c258
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c91
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testcurve25519.c56
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testdrbg.c206
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testmodes.c890
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.c118
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc4961
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testpoly1305.c102
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsalsa20.c210
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha.h213
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha1.c55
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha2.c224
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha3.c104
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testutil.h61
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/.gitignore8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/LICENSE.txt21
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/README.md41
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm.inc820
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc2311
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc1202
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr.inc1089
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc26311
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/curve-specific.inc1248
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_project.py127
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_rules.py3
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/platform-specific.inc67
-rwxr-xr-xweb/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py188
-rwxr-xr-xweb/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py203
-rwxr-xr-xweb/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py143
-rwxr-xr-xweb/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py242
-rwxr-xr-xweb/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py327
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino85
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/emk_rules.py4
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compress.c79
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compute.c81
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c90
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c59
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example93
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/types.h108
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.c1634
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.h362
-rw-r--r--web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC_vli.h172
-rw-r--r--web/server/h2o/libh2o/deps/picotls/include/picotls.h998
-rw-r--r--web/server/h2o/libh2o/deps/picotls/include/picotls/asn1.h64
-rw-r--r--web/server/h2o/libh2o/deps/picotls/include/picotls/minicrypto.h61
-rw-r--r--web/server/h2o/libh2o/deps/picotls/include/picotls/openssl.h85
-rw-r--r--web/server/h2o/libh2o/deps/picotls/include/picotls/pembase64.h44
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/asn1.c295
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/cifra.c530
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/minicrypto-pem.c339
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/openssl.c1066
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/pembase64.c373
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/picotls.c3761
-rw-r--r--web/server/h2o/libh2o/deps/picotls/lib/uecc.c190
-rwxr-xr-xweb/server/h2o/libh2o/deps/picotls/misc/dump-github-repository.pl41
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.pbxproj1023
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/ReadMe.txt29
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj188
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj.filters150
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/ReadMe.txt29
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj140
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj.filters25
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/openssl.cnf35
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/ReadMe.txt37
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj175
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.filters123
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.user4
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/targetver.h8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wincompat.h35
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wintimeofday.c73
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs.sln78
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ReadMe.txt40
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/cert.pem20
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_cert.pem14
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_key.pem5
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-1.pem5
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-2.pem9
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-3.pem5
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-4.pem5
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key.pem28
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/myec1.pem5
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/openssl.cnf35
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.c674
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj161
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.filters30
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.user4
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/targetver.h8
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj168
-rw-r--r--web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj.filters41
-rw-r--r--web/server/h2o/libh2o/deps/picotls/t/cli.c392
-rw-r--r--web/server/h2o/libh2o/deps/picotls/t/minicrypto.c165
-rw-r--r--web/server/h2o/libh2o/deps/picotls/t/openssl.c227
-rw-r--r--web/server/h2o/libh2o/deps/picotls/t/picotls.c843
-rw-r--r--web/server/h2o/libh2o/deps/picotls/t/test.h52
-rw-r--r--web/server/h2o/libh2o/deps/picotls/t/util.h240
207 files changed, 74624 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/picotls/.clang-format b/web/server/h2o/libh2o/deps/picotls/.clang-format
new file mode 100644
index 00000000..9640123c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/.clang-format
@@ -0,0 +1,7 @@
+# requires clang-format >= 3.6
+BasedOnStyle: "LLVM"
+IndentWidth: 4
+ColumnLimit: 132
+BreakBeforeBraces: Linux
+AllowShortFunctionsOnASingleLine: None
+SortIncludes: false
diff --git a/web/server/h2o/libh2o/deps/picotls/.gitignore b/web/server/h2o/libh2o/deps/picotls/.gitignore
new file mode 100644
index 00000000..4d46b407
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/.gitignore
@@ -0,0 +1,24 @@
+*/Debug
+Debug
+*/Release
+Release
+*/x64
+x64
+*/.vs
+.vs
+*/Generated Files
+*.sdf
+*/*.sdf
+*/*.user
+*.ipch
+*/*.ipch
+*.db
+*/*.db
+*/*.lib
+*/*.pdb
+*/AppX
+*/*.exe
+*/*.dll
+*/*.xbf
+*/*.ilk
+deps/picotest
diff --git a/web/server/h2o/libh2o/deps/picotls/.gitmodules b/web/server/h2o/libh2o/deps/picotls/.gitmodules
new file mode 100644
index 00000000..37df0c6d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "deps/picotest"]
+ path = deps/picotest
+ url = https://github.com/h2o/picotest.git
diff --git a/web/server/h2o/libh2o/deps/picotls/.travis.yml b/web/server/h2o/libh2o/deps/picotls/.travis.yml
new file mode 100644
index 00000000..6c822845
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/.travis.yml
@@ -0,0 +1,17 @@
+# use trusty beta (ubuntu 14.04)
+sudo: required
+dist: trusty
+
+language: c
+
+compiler:
+ - gcc
+ - clang
+
+before_install:
+ - sudo apt-get install --yes cmake
+
+script:
+ - cmake .
+ - make all
+ - make check
diff --git a/web/server/h2o/libh2o/deps/picotls/CMakeLists.txt b/web/server/h2o/libh2o/deps/picotls/CMakeLists.txt
new file mode 100644
index 00000000..87d14724
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/CMakeLists.txt
@@ -0,0 +1,51 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
+CMAKE_POLICY(SET CMP0003 NEW)
+
+PROJECT(picotls)
+
+FIND_PACKAGE(PkgConfig REQUIRED)
+
+SET(CMAKE_C_FLAGS "-std=c99 -Wall -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS}")
+INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR} deps/cifra/src/ext deps/cifra/src deps/micro-ecc deps/picotest include)
+SET(MINICRYPTO_LIBRARY_FILES
+ deps/micro-ecc/uECC.c
+ deps/cifra/src/aes.c
+ deps/cifra/src/blockwise.c
+ deps/cifra/src/chacha20.c
+ deps/cifra/src/chash.c
+ deps/cifra/src/curve25519.c
+ deps/cifra/src/drbg.c
+ deps/cifra/src/hmac.c
+ deps/cifra/src/gcm.c
+ deps/cifra/src/gf128.c
+ deps/cifra/src/modes.c
+ deps/cifra/src/poly1305.c
+ deps/cifra/src/sha256.c
+ deps/cifra/src/sha512.c)
+
+ADD_LIBRARY(picotls-core lib/picotls.c lib/pembase64.c)
+ADD_LIBRARY(picotls-minicrypto ${MINICRYPTO_LIBRARY_FILES} lib/cifra.c lib/minicrypto-pem.c lib/uecc.c lib/asn1.c)
+ADD_EXECUTABLE(test-minicrypto.t ${MINICRYPTO_LIBRARY_FILES} deps/picotest/picotest.c t/picotls.c t/minicrypto.c lib/asn1.c lib/pembase64.c)
+
+SET(TEST_EXES test-minicrypto.t)
+
+FIND_PACKAGE(OpenSSL)
+IF (OPENSSL_FOUND AND NOT (OPENSSL_VERSION VERSION_LESS "1.0.1"))
+ MESSAGE(WARNING "Enabling OpenSSL support")
+ INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+ ADD_LIBRARY(picotls-openssl lib/openssl.c)
+ ADD_EXECUTABLE(cli t/cli.c lib/pembase64.c)
+ TARGET_LINK_LIBRARIES(cli picotls-openssl picotls-core ${OPENSSL_LIBRARIES} ${CMAKE_DL_LIBS})
+ ADD_EXECUTABLE(test-openssl.t ${MINICRYPTO_LIBRARY_FILES} lib/cifra.c lib/uecc.c lib/asn1.c lib/pembase64.c deps/picotest/picotest.c t/picotls.c t/openssl.c)
+ SET_TARGET_PROPERTIES(test-openssl.t PROPERTIES COMPILE_FLAGS "-DPTLS_MEMORY_DEBUG=1")
+ TARGET_LINK_LIBRARIES(test-openssl.t ${OPENSSL_LIBRARIES} ${CMAKE_DL_LIBS})
+ SET(TEST_EXES ${TEST_EXES} test-openssl.t)
+ELSE ()
+ MESSAGE(WARNING "Disabling OpenSSL support (requires 1.0.1 or newer)")
+ENDIF ()
+
+ADD_CUSTOM_TARGET(check prove --exec '' -v ./*.t DEPENDS ${TEST_EXES})
+
+IF ("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
+ TARGET_LINK_LIBRARIES(cli "socket" "nsl")
+ENDIF ()
diff --git a/web/server/h2o/libh2o/deps/picotls/README.md b/web/server/h2o/libh2o/deps/picotls/README.md
new file mode 100644
index 00000000..12f58724
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/README.md
@@ -0,0 +1,78 @@
+picotls
+===
+
+[![Build Status](https://travis-ci.org/h2o/picotls.svg?branch=master)](https://travis-ci.org/h2o/picotls)
+
+Picotls is a [TLS 1.3](https://tlswg.github.io/tls13-spec/) implementation written in C.
+
+At the moment, the library implements draft-22 of the specification, including support 0-RTT resumption using PSK or PSK-DHE.
+
+Primary goal of the project is to create a fast, tiny TLS 1.3 implementation that can be used with the HTTP/2 protocol stack and possibly the upcoming QUIC stack of the [H2O HTTP/2 server](https://h2o.examp1e.net).
+
+Picotls only implements the communination protocol; cryptographic operations are delegated to cryptographic engines.
+At the moment, _minicrypto_ binding (uses [cifra](https://github.com/ctz/cifra/) and [micro-ecc](https://github.com/kmackay/micro-ecc)) and _openssl_ binding are provided.
+
+License and algorithms supported by the bindings are as follows:
+
+| Binding | License | Key Exchange | Certificate | AEAD cipher |
+|:-----:|:-----:|:-----:|:-----:|:-----:|
+| minicrypto | [CC0](https://github.com/ctz/cifra/) / [2-clause BSD](https://github.com/kmackay/micro-ecc) | secp256r1, x25519 | ECDSA (P256)<sup>1</sup> | AES-128-GCM |
+| OpenSSL | OpenSSL | secp256r1 | RSA, ECDSA (P256) | AES-128-GCM |
+
+Note 1: Minicrypto binding is capable of signing a handshake using the certificate's key, but cannot verify a signature sent by the peer.
+
+Building picotls
+---
+
+If you have cloned picotls from git then ensure that you have initialised the submodules:
+```
+% git submodule init
+% git submodule update
+```
+
+Build using cmake:
+```
+% cmake .
+% make
+% make check
+```
+
+A dedicated documentation for using picotls with Visual Studio can be found in [WindowsPort.md](WindowsPort.md).
+
+Developer documentation
+---
+
+Developer documentation should be available on [the wiki](https://github.com/h2o/picotls/wiki).
+
+Using the cli command
+---
+
+Run the test server (at 127.0.0.1:8443):
+```
+% ./cli -c /path/to/certificate.pem -k /path/to/private-key.pem 127.0.0.1 8443
+```
+
+Connect to the test server:
+```
+% ./cli 127.0.0.1 8443
+```
+
+Using resumption:
+```
+% ./cli -s session-file 127.0.0.1 8443
+```
+The session-file is read-write.
+The cli server implements a single-entry session cache.
+The cli server sends NewSessionTicket when it first sends application data after receiving ClientFinished.
+
+Using early-data:
+```
+% ./cli -s session-file -e 127.0.0.1 8443
+```
+When `-e` option is used, client first waits for user input, and then sends CLIENT_HELLO along with the early-data.
+
+License
+---
+
+The software is provided under the MIT license.
+Note that additional licences apply if you use the minicrypto binding (see above).
diff --git a/web/server/h2o/libh2o/deps/picotls/WindowsPort.md b/web/server/h2o/libh2o/deps/picotls/WindowsPort.md
new file mode 100644
index 00000000..b2989e3d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/WindowsPort.md
@@ -0,0 +1,34 @@
+Compiling PicoTLS with Visual Studio 2017
+
+The source contains a Visual Studio 2017 solution (picotls/picotlsvs/picotlsvs.sln)
+which itself contains 5 projects:
+
+* Three libraries, picotls.lib and its dependencies cifra.lib and uecc.lib;
+
+* A test project, testopenssl.exe, which will run on a console and
+ execute the OpenSSL tests;
+
+* And, an example project, picotlsvs.exe, which will perform a TLS exchange
+ in memory, and demonstrate how to use PicoTLS in windows.
+
+The code has a dependency on OpenSSL. When building the 32 bit projects (WIN32) it
+expects to find:
+
+* OpenSSL header files under $(OPENSSLDIR)\include
+
+* OpenSSL library libcrypto.lib under $(OPENSSLDIR)
+
+When building the 64 bits projects (X64), it expects to find:
+
+* OpenSSL header files under $(OPENSSL64DIR)\include
+
+* OpenSSL library libcrypto.lib under $(OPENSSL64DIR)
+
+You will need also to copy libcrypto.dll to the library that contains your
+executable, or to otherwise register that library. Be sure to copy the 32 bit
+library or 64 bit library, depending on which type of project you build.
+
+Only two configurations are tested: "X86 Debug" and "X86 Release". The X64 configurations
+will compile, but are not tested yet.
+
+Feel free to provide feedback and contribute.
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/.travis.yml b/web/server/h2o/libh2o/deps/picotls/deps/cifra/.travis.yml
new file mode 100644
index 00000000..44b1a26f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/.travis.yml
@@ -0,0 +1,29 @@
+language: c
+
+before_install:
+ - sudo pip install cpp-coveralls
+
+script:
+ - cd src
+ - make clean
+ - make test
+
+after_success:
+ - coveralls --exclude src/ext --gcov-options '\-lp'
+
+compiler:
+ - gcc
+
+env:
+ global:
+ - secure: "W9IUnUWNc03gIBGLPOxXCVJUOb3RY2fS4lgOo+wIsCSk0rsJAB6gruAZDoz1sMxCJyBhCv0dKV5WPkAxkZ0y55wiuUcCepgR0qis6S6rJxldPdEWc3RQaeU9LbVRKRBYUBqSsFlXr5pdOvl0CBDWmx8lhcRxAw8z+JVDrAGVsTQ="
+
+addons:
+ coverity_scan:
+ project:
+ name: "ctz/cifra"
+ description: "Cifra is a collection of cryptographic primitives targeted at embedded use."
+ notification_email: jpixton@gmail.com
+ build_command_prepend: "cd src ; make clean"
+ build_command: "make"
+ branch_pattern: coverity-scan
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/COPYING b/web/server/h2o/libh2o/deps/picotls/deps/cifra/COPYING
new file mode 100644
index 00000000..0e259d42
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/COPYING
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/README.md b/web/server/h2o/libh2o/deps/picotls/deps/cifra/README.md
new file mode 100644
index 00000000..e972912e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/README.md
@@ -0,0 +1,246 @@
+# Cifra
+Cifra is a collection of cryptographic primitives targeted at embedded use.
+
+[![Build Status](https://travis-ci.org/ctz/cifra.svg?branch=master)](https://travis-ci.org/ctz/cifra)
+
+[![Documentation](https://readthedocs.org/projects/pip/badge/)](https://cifra.readthedocs.org/en/latest/)
+
+[![Analysis Status](https://scan.coverity.com/projects/4324/badge.svg)](https://scan.coverity.com/projects/4324)
+
+[![Coverage Status](https://coveralls.io/repos/ctz/cifra/badge.svg?branch=coveralls-scan)](https://coveralls.io/r/ctz/cifra?branch=coveralls-scan)
+
+## Aims
+In order of descending emphasis, cifra aims for:
+
+* **Clarity** and **simplicity**.
+* Countermeasures for side channel leaks inherent in some
+ algorithms.
+* Suitability for embedded use. Particularly: cifra uses an
+ absolute minimum of the standard C library and is reasonably
+ efficient with respect to code and data space.
+
+## Features
+* **AES** in the **GCM**, **CCM**, **EAX** and **OCB** authenticated encryption modes.
+* **NORX** authenticated encryption system.
+* **SHA224**, **SHA256**, **SHA384** and **SHA512** hash functions (including **HMAC** and **PBKDF2**).
+* **SHA3-224**, **SHA3-256**, **SHA3-384**, **SHA3-512** hash functions (FIPS 202 compatible).
+* **ChaCha20** and **Salsa20** stream ciphers.
+* **Poly1305** one time MAC.
+* 100% code coverage by line, zero static analysis defects, valgrind-clean.
+
+Additionally cifra imports curve25519 from elsewhere (&mu;NaCl, NaCl, tweetNaCl,
+Adam Langley's curve25519-donna) for comparison between various implementations
+on embedded targets.
+
+## Documentation
+Available at [Read the Docs](https://cifra.readthedocs.org/en/latest/).
+
+## Testing
+There is quite a lot of testing available:
+
+* **Host builds**: run `make test` in the `src` directory. This builds and
+ runs assorted test programs.
+* **Emulated embedded builds**: run `make test` in the `src/arm` directory. This
+ expects to find `qemu-system-gnuarmeclipse` on the path. These tests assume
+ a Cortex-M3 target.
+* **Cortex-M0 on-target tests**: run `make test.stm32f0` in the `src/arm` directory.
+ This expects to find `openocd` on the path, with an STM32F0xx attached via
+ stlinkv2. It uses ARM semihosting to report results.
+* **Cortex-M3/4 on-target tests**: run `make test.stm32f1` or `make test.stm32f3` as above.
+
+Additionally all embedded targets expect to find the `arm-none-eabi` toolchain
+to be on the path.
+
+## Measurements
+All measurements performed at `-Os` (optimise for space), on the following MCUs:
+
+Core | Part number | Price (1s) | Max clock | Flash | SRAM
+---------- | ------------- | ------------ | ---------- | ----- | -----
+Cortex-M0 | STM32F030F4P6 | 1.17EUR | 48MHz | 16KB | 4KB
+Cortex-M3 | STM32F103C8T6 | 2.87EUR | 72MHz | 64KB | 20KB
+Cortex-M4F | STM32F303K6T6 | 4.53EUR | 72MHz | 32KB | 12KB
+
+More measurements are available for AEAD modes on my blog post:
+[Benchmarking Modern Authenticated Encryption on €1 devices](http://jbp.io/2015/06/01/modern-authenticated-encryption-for-1-euro/).
+
+## AES
+This test does a key schedule, then encrypts one block.
+
+### 128-bit key
+Core | Cycles (key schedule + block) | Cycles (key schedule) | Cycles (block) | Stack | Code size
+---------- | ----------------------------- | --------------------- | -------------- | ----- | ---------
+Cortex-M0 | 7156 | 2147 | 5009 | 312B | 1020B
+Cortex-M3 | 4692 | 1591 | 3101 | 300B | 960B
+Cortex-M4F | 4591 | 1571 | 3020 | 300B | 960B
+
+### 256-bit key
+Core | Cycles (key schedule + block) | Cycles (key schedule) | Cycles (block) | Stack | Code size
+---------- | ----------------------------- | --------------------- | -------------- | ----- | ---------
+Cortex-M0 | 10611 | 3650 | 6961 | 396B | 1100B
+Cortex-M3 | 6735 | 2450 | 4285 | 380B | 1048B
+Cortex-M4F | 6588 | 2416 | 4172 | 380B | 1048B
+
+## AES128-GCM
+This test encrypts and authenticates a 16 byte message,
+with 16 bytes additionally authenticated data. It includes
+the initial key schedule.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 57022 | 796B | 2600B
+Cortex-M3 | 44306 | 812B | 2644B
+Cortex-M4F | 43657 | 812B | 2644B
+
+## AES128-EAX
+This test encrypts and authenticates a 16 byte message,
+with 16 bytes additionally authenticated data. It includes
+the initial key schedule.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 50564 | 932B | 2836B
+Cortex-M3 | 32855 | 932B | 2780B
+Cortex-M4F | 32159 | 932B | 2780B
+
+## AES128-CCM
+This test encrypts and authenticates a 16 byte message,
+with 16 bytes additionally authenticated data. It includes
+the initial key schedule.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 37677 | 772B | 2280B
+Cortex-M3 | 24462 | 780B | 2256B
+Cortex-M4F | 23949 | 780B | 2256B
+
+## NORX32
+This test encrypts and authenticates a 16 byte message,
+with 16 bytes additionally authenticated data.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 10692 | 320B | 1636B
+Cortex-M3 | 6909 | 320B | 1820B
+Cortex-M4F | 6855 | 320B | 1820B
+
+## ChaCha20
+This test encrypts a 64 byte message.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 5981 | 564B | 1416B
+Cortex-M3 | 3487 | 544B | 1328B
+Cortex-M4F | 3468 | 544B | 1328B
+
+(For comparison with AES, add an AES256 key schedule plus 4 blocks.
+That's about 33K cycles.)
+
+## Salsa20
+This test encrypts a 64 byte message.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 6173 | 560B | 1412B
+Cortex-M3 | 3320 | 552B | 1272B
+Cortex-M4F | 3311 | 552B | 1272B
+
+## SHA256
+This test hashes the empty string (one compression function invocation).
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 11561 | 312B | 1760B
+Cortex-M3 | 6530 | 300B | 1708B
+Cortex-M4F | 6278 | 300B | 1708B
+
+## SHA512
+This test hashes the empty string (one compression function invocation).
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 38447 | 796B | 2888B
+Cortex-M3 | 28771 | 836B | 2988B
+Cortex-M4F | 28777 | 836B | 2980B
+
+## SHA3-256
+This test hashes the empty string (one sponge permutation).
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 93648 | 848B | 2212B
+Cortex-M3 | 74321 | 856B | 2164B
+Cortex-M4F | 72215 | 856B | 2140B
+
+## SHA3-512
+This test hashes the empty string (one sponge permutation).
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 92565 | 880B | 2212B
+Cortex-M3 | 73509 | 888B | 2164B
+Cortex-M4F | 71419 | 888B | 2140B
+
+## HMAC-SHA256
+This test computes a MAC with a 32 byte key over the
+message "hello world".
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 48924 | 1328B | 2200B
+Cortex-M3 | 28333 | 1324B | 2132B
+Cortex-M4F | 27337 | 1324B | 2132B
+
+## Poly1305-AES
+This test computes a MAC with a 32 byte key over the
+message "hello world". It includes the AES nonce
+processing.
+
+Core | Cycles | Stack | Code size
+---------- | ------ | ----- | ---------
+Cortex-M0 | 15719 | 704B | 1920B
+Cortex-M3 | 11328 | 696B | 1964B
+Cortex-M4F | 10706 | 696B | 1932B
+
+## Curve25519
+This test is one point multiplication.
+
+This uses the implementation from [&mu;NaCl](http://munacl.cryptojedi.org/curve25519-cortexm0.shtml)
+by Düll, Haase, Hinterwälder, Hutter, Paar, Sánchez and Schwabe.
+
+Core | Cycles | Stack | Code size
+---------- | ------- | ----- | ---------
+Cortex-M0 | 4070271 | 464B | 5596B
+Cortex-M3 | 3720363 | 448B | 5536B
+Cortex-M4F | 3720105 | 448B | 5536B
+
+See [curve25519-shootout](curve25519-shootout.md) for comparitive measurements
+for other curve25519 implementations.
+
+## C library requirements
+Cifra requires `memcpy`, `memset`, and `abort`.
+
+## Future
+* ~~Keccak hash function (aka SHA3)~~.
+* ~~Poly1305 one-time MAC~~.
+* Constant time curve25519 for Cortex-M4F using the FPU.
+* Constant time curve25519 for Cortex-M3 (avoiding the variable-time multiplier).
+
+## Notable past bugs/advisories
+* [Issue #2](https://github.com/ctz/cifra/issues/2): in all versions before commit
+ [d62aa26e](https://github.com/ctz/cifra/commit/d62aa26e2c3c49e5b8a4298644cff290406d9357)
+ (September 16th 2015) too much padding was added when hashing messages of certain
+ lengths. Specifically, messages whose length satisfied `len % 64 = 55` for
+ SHA1/SHA224/SHA256 or `len % 128 = 119` for SHA384/SHA512. SHA3 was not affected.
+ Better testing is now in place.
+* [Issue #3](https://github.com/ctz/cifra/issues/3): in all versions before commit
+ [82d77cd8](https://github.com/ctz/cifra/commit/82d77cd8323f6d4473fcb68517752a778970138d)
+ (April 16th 2016) EAX would produce wrong tags for empty AADs or messages. The
+ underlying CMAC is now more resistant to this case.
+
+## License
+[CC0](https://creativecommons.org/publicdomain/zero/1.0/).
+
+Please attribute the author. This is a request only, and not a license term.
+
+## Author
+Joseph Birr-Pixton <jpixton@gmail.com>
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/curve25519-shootout.md b/web/server/h2o/libh2o/deps/picotls/deps/cifra/curve25519-shootout.md
new file mode 100644
index 00000000..6f057589
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/curve25519-shootout.md
@@ -0,0 +1,16 @@
+## Curve25519 on Cortex-M0 shootout
+Implementation | Optimisation | Cycles | Code size | Stack usage
+-------------- | ------------ | --------- | --------- | -----------
+donna | `-Os` | 15748K | 7.4KB | 3148B
+donna | `-O2` | 15218K | 7.9KB | 3148B
+donna | `-O3` | 12907K | 16KB | 3380B
+naclref | `-Os` | 47813K | 3.2KB | 4012B
+naclref | `-O2` | 34309K | 3.5KB | 4036B
+naclref | `-O3` | 35059K | 4.1KB | 4044B
+tweetnacl | `-Os` | 75979K | 2.8KB | 2244B
+tweetnacl | `-O2` | 68876K | 3.0KB | 2268B
+tweetnacl | `-O3` | 69622K | 8.9KB | 2900B
+
+naclref at -O2 seems to give a good balance. If you can spare the flash,
+donna is quite significantly quicker.
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/Makefile b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/Makefile
new file mode 100644
index 00000000..2b7f5c03
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/Makefile
@@ -0,0 +1,3 @@
+default: all
+all:
+ sphinx-build -b html . _build
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/build.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/build.py
new file mode 100644
index 00000000..0b006825
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/build.py
@@ -0,0 +1,274 @@
+"""
+Extracts documentation from cifra headers.
+
+We want to embed documentation in headers for good
+locality. But want to write rst for formatting by sphinx.
+This is a problem.
+
+'Breathe' provides a bridge between doxygen and sphinx,
+but doxygen's documentation markup is pretty awful.
+
+Therefore, we write rst directly in C headers, and then
+extract it here. The rules are: a C block comment
+starting exactly '/* .. ' is dedented, and then included
+verbatim. The convention is that the documentation
+preceeds the C declarations they apply to, and that struct
+members are documented before the struct they are contained
+within. eg:
+
+/* .. c:function:: int foo(int bar)
+ * Foos a bar, returning the foo coefficient.
+ */
+int foo(int bar);
+
+/* .. c:type:: thing
+ * Container for things.
+ *
+ * .. c:member:: int thing.foo
+ * Count of foos.
+ *
+ * .. c:member:: int thing.bar
+ * Count of bars.
+ */
+typedef struct
+{
+ int foo;
+ int bar;
+} thing;
+
+As a special effect, the following tokens are replaced
+in the comments:
+
+ - $DECL: the immediately following function declaration
+"""
+
+import glob
+import re
+import StringIO
+
+# We know which headers constitute the external interface.
+EXTERNAL = """
+aes
+cf_config
+chash
+hmac
+modes
+pbkdf2
+prp
+salsa20
+sha1
+sha2
+sha3
+norx
+poly1305
+chacha20poly1305
+drbg
+""".split()
+
+# Basic idea of a C identifier
+C_IDENTIFIER = '[a-zA-Z_][a-zA-Z0-9_]+'
+
+DECL_RE = re.compile(r'^\s*(.+?' + C_IDENTIFIER + '\(.+?\));', re.MULTILINE | re.DOTALL)
+COMMENT_RE = re.compile(r'^\s*\/\* (\.\..*?) \*\/$', re.MULTILINE | re.DOTALL)
+INTRO_RE = re.compile(r'^\s*\/\*\*(.*?)\*\/$', re.MULTILINE | re.DOTALL)
+NEW_SECTION_RE = re.compile(r'^..+\n(==+|--+)$', re.MULTILINE)
+
+class section(object):
+ def __init__(self):
+ self.intro = []
+ self.macros = []
+ self.types = []
+ self.functions = []
+ self.values = []
+
+ def __repr__(self):
+ return repr(self.format()[:30])
+
+ def __str__(self):
+ return repr(self.format()[:30])
+
+ def format(self):
+ f = StringIO.StringIO()
+
+ def emit(title, section):
+ if len(section) == 0:
+ return
+
+ if title:
+ print >>f, title
+ print >>f, '*' * len(title)
+ print >>f
+
+ for s in section:
+ print >>f, s.getvalue()
+
+ emit(None, self.intro)
+ emit('Macros', self.macros)
+ emit('Types', self.types)
+ emit('Functions', self.functions)
+ emit('Values', self.values)
+
+ return f.getvalue()
+
+ def is_empty(self):
+ items = len(self.intro) + len(self.macros) + len(self.types) + \
+ len(self.functions) + len(self.values)
+ return 0 == items
+
+ def add_item(self, sec):
+ f = StringIO.StringIO()
+ sec.append(f)
+ return f
+
+def massage_decl(decl):
+ """
+ Tart-up a C function declaration: remove storage qualifiers,
+ smush onto one line, escape asterisks.
+ """
+ for storage in 'extern static inline'.split():
+ decl = decl.replace(storage + ' ', '')
+
+ fixed_lines = ' '.join(line.strip() for line in decl.splitlines())
+
+ return fixed_lines.replace('*', '\\*')
+
+def replace_decl(comment, comment_match, header):
+ if '$DECL' not in comment:
+ return comment
+
+ start = comment_match.end(0) + 1
+ decl_match = DECL_RE.match(header, start)
+
+ if decl_match is None:
+ print 'Cause:', comment
+ print 'Trailer:', header[start:start+60]
+ raise IOError('$DECL present but cannot find following DECL')
+
+ decl = decl_match.group(1)
+ decl = massage_decl(decl)
+ return comment.replace('$DECL', decl)
+
+def decomment(lines):
+ for i in range(len(lines)):
+ if lines[i].startswith(' *'):
+ lines[i] = lines[i][3:]
+ lines[i] = lines[i].strip()
+
+def drop_empty_prefix(lines):
+ while len(lines) and lines[0] == '':
+ lines.pop(0)
+
+def starts_new_section(lines):
+ txt = '\n'.join(lines)
+ r = NEW_SECTION_RE.search(txt) is not None
+ return r
+
+def process(header, rst):
+ """
+ Converts a header into restructured text.
+
+ header is a file-like opened to read the header.
+ rst is a file-like opened to write the rst results.
+ """
+
+ hh = header.read()
+
+ # Collect definitions into sections
+ sec = None
+ all_sections = []
+ intro, macros, types, functions, values = [], [], [], [], []
+
+ def add_section():
+ if sec and not sec.is_empty():
+ all_sections.append(sec)
+ return section()
+
+ sec = add_section()
+
+ offs = 0
+
+ while True:
+ intro_match = INTRO_RE.search(hh, offs)
+ comment_match = COMMENT_RE.search(hh, offs)
+
+ if intro_match is None and comment_match is None:
+ break
+
+ # process earliest occuring
+ if intro_match is not None and (comment_match is None or intro_match.start(0) < comment_match.start(0)):
+ txt = intro_match.group(1)
+
+ lines = txt.splitlines()
+ decomment(lines)
+ drop_empty_prefix(lines)
+
+ if starts_new_section(lines):
+ sec = add_section()
+
+ outf = sec.add_item(sec.intro)
+
+ for l in lines:
+ print >>outf, l
+ offs = intro_match.end(0) + 1
+ continue
+
+ if comment_match is not None and (intro_match is None or comment_match.start(0) < intro_match.start(0)):
+ txt = comment_match.group(1)
+
+ # work out which section this goes into
+ outf = None
+ if '.. c:macro::' in txt:
+ outf = sec.add_item(sec.macros)
+ elif '.. c:type::' in txt:
+ outf = sec.add_item(sec.types)
+ elif '.. c:var::' in txt:
+ outf = sec.add_item(sec.values)
+ elif '.. c:function::' in txt:
+ outf = sec.add_item(sec.functions)
+ elif '.. c:member::' in txt:
+ if len(types) == 0:
+ raise IOError('c:member must come after a c:type')
+ outf = types[-1]
+ else:
+ raise IOError('Cannot categorise item: ' + txt)
+
+ # expand $DECL
+ txt = replace_decl(txt, comment_match, hh)
+
+ # decomment lines
+ lines = txt.splitlines()
+ decomment(lines)
+
+ # domain lines are unindented
+ while lines and lines[0].startswith('.. '):
+ print >>outf, lines.pop(0)
+ print >>outf
+
+ # empty prefix lines are stripped
+ drop_empty_prefix(lines)
+
+ # other lines are indented
+ for line in lines:
+ if len(line):
+ line = ' ' + line
+ print >>outf, line
+
+ offs = comment_match.end(0) + 1
+ continue
+
+ add_section()
+
+ for sec in all_sections:
+ rst.write(sec.format())
+
+def run():
+ for fn in EXTERNAL:
+ print '** build', fn
+ header = '../src/' + fn + '.h'
+ rst = fn + '.rst'
+ with open(header, 'r') as fh:
+ with open(rst, 'w') as fr:
+ process(fh, fr)
+
+if __name__ == '__main__':
+ run()
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/conf.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/conf.py
new file mode 100644
index 00000000..8354354c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/conf.py
@@ -0,0 +1,263 @@
+# -*- coding: utf-8 -*-
+#
+# Cifra documentation build configuration file, created by
+# sphinx-quickstart on Sat Feb 21 18:02:37 2015.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('.'))
+
+import build
+build.run()
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.mathjax',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Cifra'
+copyright = u'2015, Joseph Birr-Pixton'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.1'
+# The full version, including alpha/beta/rc tags.
+release = '0.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Cifradoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ ('index', 'Cifra.tex', u'Cifra Documentation',
+ u'Joseph Birr-Pixton', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'cifra', u'Cifra Documentation',
+ [u'Joseph Birr-Pixton'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'Cifra', u'Cifra Documentation',
+ u'Joseph Birr-Pixton', 'Cifra', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/index.rst b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/index.rst
new file mode 100644
index 00000000..e853de4a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/doc/index.rst
@@ -0,0 +1,33 @@
+.. Cifra documentation master file, created by
+ sphinx-quickstart on Sat Feb 21 18:02:37 2015.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to Cifra's documentation!
+=================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ cf_config
+ prp
+ chash
+ aes
+ norx
+ salsa20
+ modes
+ hmac
+ poly1305
+ chacha20poly1305
+ pbkdf2
+ sha1
+ sha2
+ sha3
+ drbg
+
+Index
+-----
+* :ref:`genindex`
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/.gitignore b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/.gitignore
new file mode 100644
index 00000000..2163875d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/.gitignore
@@ -0,0 +1 @@
+openssl-hash
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/Makefile b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/Makefile
new file mode 100644
index 00000000..065721c2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/Makefile
@@ -0,0 +1,13 @@
+CFLAGS += -std=gnu99 -O0 -g -Wall -Werror
+
+all: run
+
+openssl-hash: openssl-hash.c
+ $(CC) $(CFLAGS) -o $@ $^ -lcrypto
+
+run: openssl-hash
+ ./openssl-hash
+ python python-hash.py
+
+clean:
+ rm -rf *.o openssl-hash
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/README.md b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/README.md
new file mode 100644
index 00000000..a7d38287
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/README.md
@@ -0,0 +1,2 @@
+This directory contains assorted programs for generating test vectors
+from other crypto libraries, like OpenSSL.
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c
new file mode 100644
index 00000000..9df68566
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/openssl-hash.c
@@ -0,0 +1,60 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include <openssl/evp.h>
+
+#define MAX_LENGTH 1024
+
+static void printhex(const uint8_t *buf, size_t len)
+{
+ for (size_t i = 0; i < len; i++)
+ printf("%02x", buf[i]);
+}
+
+/* This test produces a single hash value which depends on
+ * hashes with all preimage lengths up to max.
+ *
+ * It emits
+ * H(H(t(0)) || H(t(1)) || ... || H(t(max-1))))
+ * where
+ * t(n) = (n % 256) ^ n
+ * (informally, t(n) is a n-length octet string of octets with value n mod 256)
+ */
+static void emit_length_test(const char *name, const EVP_MD *h, size_t max)
+{
+ EVP_MD_CTX outer, inner;
+ EVP_DigestInit(&outer, h);
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned int digestlen;
+
+ for (size_t n = 0; n < max; n++)
+ {
+ EVP_DigestInit(&inner, h);
+ for (size_t i = 0; i < n; i++)
+ {
+ uint8_t byte = n & 0xff;
+ EVP_DigestUpdate(&inner, &byte, 1);
+ }
+ digestlen = sizeof digest;
+ EVP_DigestFinal(&inner, digest, &digestlen);
+
+ EVP_DigestUpdate(&outer, digest, digestlen);
+ }
+
+ digestlen = sizeof digest;
+ EVP_DigestFinal(&outer, digest, &digestlen);
+
+ printf("%s(%zu) = ", name, max);
+ printhex(digest, (size_t) digestlen);
+ printf("\n");
+}
+
+int main(void)
+{
+ emit_length_test("SHA1", EVP_sha1(), MAX_LENGTH);
+ emit_length_test("SHA224", EVP_sha224(), MAX_LENGTH);
+ emit_length_test("SHA256", EVP_sha256(), MAX_LENGTH);
+ emit_length_test("SHA384", EVP_sha384(), MAX_LENGTH);
+ emit_length_test("SHA512", EVP_sha512(), MAX_LENGTH);
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py
new file mode 100644
index 00000000..90aa248f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/extra_vecs/python-hash.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python2
+
+#
+# see openssl-hash for details of what this is computing
+# you'll need python-sha3 from https://github.com/bjornedstrom/python-sha3
+#
+
+import hashlib
+import sha3
+
+# check sha3 at least works; pysha3 *DOES NOT* (it is keccak, not sha3)
+assert '3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532' == hashlib.sha3_256('abc').hexdigest()
+
+def hh(x):
+ return ''.join(['\\x' + x[y:y+2] for y in range(0, len(x), 2)])
+
+def len_test(name, H, max):
+ outer = H()
+
+ for n in range(max):
+ inner = H()
+ inner.update(chr(n & 0xff) * n)
+ outer.update(inner.digest())
+
+ result = outer.hexdigest()
+ print '%s(%d) = %s or %s' % (name, max, result, hh(result))
+
+if __name__ == '__main__':
+ MAX = 1024
+ len_test('SHA1', hashlib.sha1, MAX)
+ len_test('SHA224', hashlib.sha224, MAX)
+ len_test('SHA256', hashlib.sha256, MAX)
+ len_test('SHA384', hashlib.sha384, MAX)
+ len_test('SHA512', hashlib.sha512, MAX)
+ len_test('SHA3-224', hashlib.sha3_224, MAX)
+ len_test('SHA3-256', hashlib.sha3_256, MAX)
+ len_test('SHA3-384', hashlib.sha3_384, MAX)
+ len_test('SHA3-512', hashlib.sha3_512, MAX)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/.gitignore b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/.gitignore
new file mode 100644
index 00000000..3bd32750
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/.gitignore
@@ -0,0 +1,5 @@
+*.o
+*.so
+*.gcov
+*.gcno
+*.gcda
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/Makefile b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/Makefile
new file mode 100644
index 00000000..ccbda7eb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/Makefile
@@ -0,0 +1,17 @@
+CFLAGS += -g -O0 -std=gnu99 -fPIC -Wall -Wextra -Werror -Wno-unused-parameter
+CPPFLAGS += -I../src -I../../bignum/out -I../../shitlisp/out
+
+all: cifra.so
+
+SOURCES = aes.o sha256.o sha512.o chash.o hmac.o pbkdf2.o modes.o eax.o \
+ blockwise.o cmac.o salsa20.o chacha20.o curve25519.o
+
+cifra.so: $(addprefix ../src/, $(SOURCES)) sl-cifra.o
+ $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ -shared
+
+clean:
+ rm -f *.o *.pyc $(TARGETS) *.gcov *.gcda *.gcno
+
+test: $(wildcard test-*.sl) cifra.so
+ ../../shitlisp/out/shitlisp --mod=./cifra.so $(wildcard test-*.sl)
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c
new file mode 100644
index 00000000..6d7b944f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/sl-cifra.c
@@ -0,0 +1,206 @@
+#include "handy.h"
+#include "dstr.h"
+#include "shitlisp.h"
+#include "aes.h"
+#include "sha2.h"
+#include "hmac.h"
+#include "pbkdf2.h"
+
+#include <assert.h>
+
+static sl_value * aes_block_fn(sl_value *self, sl_value *args, sl_symboltab *tab,
+ void (*blockfn)(const cf_aes_context *ctx,
+ const uint8_t *in,
+ uint8_t *out))
+{
+ sl_iter it = sl_iter_start(args);
+ sl_value *key = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+ sl_value *block = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+
+ sl_value *ret = NULL;
+
+ if (!key || !block ||
+ (key->u.bytes.len != 16 && key->u.bytes.len != 24 && key->u.bytes.len != 32) ||
+ block->u.bytes.len != AES_BLOCKSZ)
+ {
+ ret = sl_get_nil();
+ goto x_err;
+ }
+
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key->u.bytes.buf, key->u.bytes.len);
+ uint8_t blockout[AES_BLOCKSZ];
+ blockfn(&ctx, block->u.bytes.buf, blockout);
+ ret = sl_new_bytes(blockout, AES_BLOCKSZ);
+ cf_aes_finish(&ctx);
+
+x_err:
+ sl_decref(key);
+ sl_decref(block);
+ return ret;
+}
+
+static sl_value * aes_block_encrypt(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return aes_block_fn(self, args, tab, cf_aes_encrypt);
+}
+
+static sl_value * aes_block_decrypt(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return aes_block_fn(self, args, tab, cf_aes_decrypt);
+}
+
+/* Hashing */
+static sl_value * hash_fn(sl_value *self, sl_value *args, sl_symboltab *tab, const cf_chash *h)
+{
+ sl_iter it = sl_iter_start(args);
+ sl_value *msg = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+
+ if (!msg)
+ return sl_get_nil();
+
+ cf_chash_ctx ctx;
+ assert(h->ctxsz <= CF_CHASH_MAXCTX);
+ h->init(&ctx);
+ h->update(&ctx, msg->u.bytes.buf, msg->u.bytes.len);
+ sl_decref(msg);
+
+ uint8_t result[CF_MAXHASH];
+ assert(h->hashsz <= CF_MAXHASH);
+ h->digest(&ctx, result);
+
+ return sl_new_bytes(result, h->hashsz);
+}
+
+static sl_value * sha224(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return hash_fn(self, args, tab, &cf_sha224);
+}
+
+static sl_value * sha256(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return hash_fn(self, args, tab, &cf_sha256);
+}
+
+static sl_value * sha384(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return hash_fn(self, args, tab, &cf_sha384);
+}
+
+static sl_value * sha512(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return hash_fn(self, args, tab, &cf_sha512);
+}
+
+/* HMAC */
+static sl_value * hmac_fn(sl_value *self, sl_value *args, sl_symboltab *tab, const cf_chash *h)
+{
+ sl_iter it = sl_iter_start(args);
+ sl_value *key = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+ sl_value *msg = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+
+ if (!key || !msg)
+ {
+ sl_decref(key);
+ sl_decref(msg);
+ return sl_get_nil();
+ }
+
+ uint8_t result[CF_MAXHASH];
+ cf_hmac(key->u.bytes.buf, key->u.bytes.len,
+ msg->u.bytes.buf, msg->u.bytes.len,
+ result,
+ h);
+
+ sl_decref(key);
+ sl_decref(msg);
+ return sl_new_bytes(result, h->hashsz);
+}
+
+static sl_value * hmac_sha224(sl_value *self, sl_value *args, sl_symboltab *tab)
+{ return hmac_fn(self, args, tab, &cf_sha224); }
+
+static sl_value * hmac_sha256(sl_value *self, sl_value *args, sl_symboltab *tab)
+{ return hmac_fn(self, args, tab, &cf_sha256); }
+
+static sl_value * hmac_sha384(sl_value *self, sl_value *args, sl_symboltab *tab)
+{ return hmac_fn(self, args, tab, &cf_sha384); }
+
+static sl_value * hmac_sha512(sl_value *self, sl_value *args, sl_symboltab *tab)
+{ return hmac_fn(self, args, tab, &cf_sha512); }
+
+
+/* PBKDF2 */
+static sl_value * do_pbkdf2(const cf_chash *h, sl_value *pw, sl_value *salt,
+ uint32_t iterations, uint32_t outlen)
+{
+ dstr out;
+ dstr_init(&out);
+ if (dstr_expand(&out, outlen))
+ return NULL;
+
+ cf_pbkdf2_hmac(pw->u.bytes.buf, pw->u.bytes.len,
+ salt->u.bytes.buf, salt->u.bytes.len,
+ iterations,
+ (uint8_t *) out.start, outlen,
+ h);
+
+ sl_value *ret = sl_new_bytes((uint8_t *) out.start, outlen);
+ dstr_free(&out);
+ return ret;
+}
+
+static sl_value * pbkdf2_fn(sl_value *self, sl_value *args, sl_symboltab *tab, const cf_chash *h)
+{
+ sl_iter it = sl_iter_start(args);
+ sl_value *pw = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+ sl_value *salt = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_bytes, tab);
+ sl_value *iterations = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_integer, tab);
+ sl_value *outlen = sl_iter_convert(&it, sl_preprocess_eval, sl_assert_integer, tab);
+
+ sl_value *ret;
+
+ if (!pw || !salt || !iterations || !outlen)
+ ret = sl_get_nil();
+ else
+ {
+ assert(bignum_len_words(&iterations->u.integer.bn) == 1);
+ assert(bignum_len_words(&outlen->u.integer.bn) == 1);
+ ret = do_pbkdf2(h, pw, salt,
+ iterations->u.integer.bn.v[0],
+ outlen->u.integer.bn.v[0]);
+ }
+
+ sl_decref(pw);
+ sl_decref(salt);
+ sl_decref(iterations);
+ sl_decref(outlen);
+ return ret;
+}
+
+static sl_value * pbkdf2_sha224(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return pbkdf2_fn(self, args, tab, &cf_sha224);
+}
+
+static sl_value * pbkdf2_sha256(sl_value *self, sl_value *args, sl_symboltab *tab)
+{
+ return pbkdf2_fn(self, args, tab, &cf_sha256);
+}
+
+int SL_MODULE_ENTRY(sl_symboltab *tab)
+{
+ ER(sl_symboltab_add_name_native(tab, "aes-encrypt", aes_block_encrypt));
+ ER(sl_symboltab_add_name_native(tab, "aes-decrypt", aes_block_decrypt));
+ ER(sl_symboltab_add_name_native(tab, "sha224", sha224));
+ ER(sl_symboltab_add_name_native(tab, "sha256", sha256));
+ ER(sl_symboltab_add_name_native(tab, "sha384", sha384));
+ ER(sl_symboltab_add_name_native(tab, "sha512", sha512));
+ ER(sl_symboltab_add_name_native(tab, "hmac-sha224", hmac_sha224));
+ ER(sl_symboltab_add_name_native(tab, "hmac-sha256", hmac_sha256));
+ ER(sl_symboltab_add_name_native(tab, "hmac-sha384", hmac_sha384));
+ ER(sl_symboltab_add_name_native(tab, "hmac-sha512", hmac_sha512));
+ ER(sl_symboltab_add_name_native(tab, "pbkdf2-sha224", pbkdf2_sha224));
+ ER(sl_symboltab_add_name_native(tab, "pbkdf2-sha256", pbkdf2_sha256));
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl
new file mode 100644
index 00000000..5535c5de
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-aes.sl
@@ -0,0 +1,91 @@
+(def check-aes (key pt ct)
+ (+
+ (assert (=
+ ct
+ (aes-encrypt key pt)))
+ (assert (=
+ pt
+ (aes-decrypt key ct)))
+ )
+)
+
+(check-aes
+ [000102030405060708090a0b0c0d0e0f]
+ [00112233445566778899aabbccddeeff]
+ [69c4e0d86a7b0430d8cdb78070b4c55a]
+)
+(check-aes
+ [000102030405060708090a0b0c0d0e0f1011121314151617]
+ [00112233445566778899aabbccddeeff]
+ [dda97ca4864cdfe06eaf70a0ec0d7191]
+)
+(check-aes
+ [000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f]
+ [00112233445566778899aabbccddeeff]
+ [8ea2b7ca516745bfeafc49904b496089]
+)
+
+(check-aes
+ [2b7e151628aed2a6abf7158809cf4f3c]
+ [6bc1bee22e409f96e93d7e117393172a]
+ [3ad77bb40d7a3660a89ecaf32466ef97]
+)
+(check-aes
+ [2b7e151628aed2a6abf7158809cf4f3c]
+ [ae2d8a571e03ac9c9eb76fac45af8e51]
+ [f5d3d58503b9699de785895a96fdbaaf]
+)
+(check-aes
+ [2b7e151628aed2a6abf7158809cf4f3c]
+ [30c81c46a35ce411e5fbc1191a0a52ef]
+ [43b1cd7f598ece23881b00e3ed030688]
+)
+(check-aes
+ [2b7e151628aed2a6abf7158809cf4f3c]
+ [f69f2445df4f9b17ad2b417be66c3710]
+ [7b0c785e27e8ad3f8223207104725dd4]
+)
+
+(check-aes
+ [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b]
+ [6bc1bee22e409f96e93d7e117393172a]
+ [bd334f1d6e45f25ff712a214571fa5cc]
+)
+(check-aes
+ [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b]
+ [ae2d8a571e03ac9c9eb76fac45af8e51]
+ [974104846d0ad3ad7734ecb3ecee4eef]
+)
+(check-aes
+ [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b]
+ [30c81c46a35ce411e5fbc1191a0a52ef]
+ [ef7afd2270e2e60adce0ba2face6444e]
+)
+(check-aes
+ [8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b]
+ [f69f2445df4f9b17ad2b417be66c3710]
+ [9a4b41ba738d6c72fb16691603c18e0e]
+)
+
+(check-aes
+ [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4]
+ [6bc1bee22e409f96e93d7e117393172a]
+ [f3eed1bdb5d2a03c064b5a7e3db181f8]
+)
+(check-aes
+ [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4]
+ [ae2d8a571e03ac9c9eb76fac45af8e51]
+ [591ccb10d410ed26dc5ba74a31362870]
+)
+(check-aes
+ [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4]
+ [30c81c46a35ce411e5fbc1191a0a52ef]
+ [b6ed21b99ca6f4f9f153e7b1beafed1d]
+)
+(check-aes
+ [603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4]
+ [f69f2445df4f9b17ad2b417be66c3710]
+ [23304b7a39f9f3ff067d8d8f9e24ecc7]
+)
+
+(puts success)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl
new file mode 100644
index 00000000..b87f3970
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-pbkdf2.sl
@@ -0,0 +1,36 @@
+(assert (=
+ (pbkdf2-sha256 (bytes "password") (bytes "salt") 1 32)
+ [120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b])
+)
+
+(assert (=
+ (pbkdf2-sha256 (bytes "password") (bytes "salt") 2 32)
+ [ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43])
+)
+
+(assert (=
+ (pbkdf2-sha256 (bytes "password") (bytes "salt") 4096 32)
+ [c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a])
+)
+
+(assert (=
+ (pbkdf2-sha256 (bytes "passwordPASSWORDpassword") (bytes "saltSALTsaltSALTsaltSALTsaltSALTsalt") 4096 40)
+ [348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9])
+)
+
+(assert (=
+ (pbkdf2-sha256 [] (bytes "salt") 1024 32)
+ [9e83f279c040f2a11aa4a02b24c418f2d3cb39560c9627fa4f47e3bcc2897c3d])
+)
+
+(assert (=
+ (pbkdf2-sha256 (bytes "password") [] 1024 32)
+ [ea5808411eb0c7e830deab55096cee582761e22a9bc034e3ece925225b07bf46])
+)
+
+(assert (=
+ (pbkdf2-sha256 [7061737300776f7264] [7361006c74] 4096 16)
+ [89b69d0516f829893c696226650a8687])
+)
+
+(puts success)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl
new file mode 100644
index 00000000..5de9e151
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha224.sl
@@ -0,0 +1,41 @@
+(assert (=
+ (sha224 (bytes "abc"))
+ [23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7])
+)
+
+(assert (=
+ (sha224 [])
+ [d14a028c 2a3a2bc9 476102bb 288234c4 15a2b01f 828ea62a c5b3e42f])
+)
+
+(assert (=
+ (hmac-sha224 (* [0b] 20) (bytes "Hi There"))
+ [896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22])
+)
+
+(assert (=
+ (hmac-sha224 (bytes "Jefe") (bytes "what do ya want for nothing?"))
+ [a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44])
+)
+
+(assert (=
+ (hmac-sha224 (* [aa] 20) (* [dd] 50))
+ [7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea])
+)
+
+(assert (=
+ (hmac-sha224 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50))
+ [6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a])
+)
+
+(assert (=
+ (hmac-sha224 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First"))
+ [95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e])
+)
+
+(assert (=
+ (hmac-sha224 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))
+ [3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1])
+)
+
+(puts success)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl
new file mode 100644
index 00000000..83c04573
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha256.sl
@@ -0,0 +1,62 @@
+(assert (=
+ (sha256 (bytes "abc"))
+ [ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad])
+)
+
+(assert (=
+ (sha256 (bytes "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))
+ [248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1])
+)
+
+(assert (=
+ (sha256 (* (bytes "a") 1000000))
+ [cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0])
+)
+
+(assert (=
+ (sha256 (bytes "The quick brown fox jumps over the lazy dog"))
+ [d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592])
+)
+
+(assert (=
+ (sha256 (bytes "The quick brown fox jumps over the lazy cog"))
+ [e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be])
+)
+
+(assert (=
+ (sha256 [])
+ [e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855])
+)
+
+(assert (=
+ (hmac-sha256 (* [0b] 20) (bytes "Hi There"))
+ [b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7])
+)
+
+(assert (=
+ (hmac-sha256 (bytes "Jefe") (bytes "what do ya want for nothing?"))
+ [5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843])
+)
+
+(assert (=
+ (hmac-sha256 (* [aa] 20) (* [dd] 50))
+ [773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe])
+)
+
+(assert (=
+ (hmac-sha256 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50))
+ [82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b])
+)
+
+(assert (=
+ (hmac-sha256 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First"))
+ [60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54])
+)
+
+(assert (=
+ (hmac-sha256 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))
+ [9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2])
+)
+
+
+(puts success)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl
new file mode 100644
index 00000000..33a00ee6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha384.sl
@@ -0,0 +1,67 @@
+(assert (=
+ (sha384 (bytes "abc"))
+ [cb00753f45a35e8b b5a03d699ac65007 272c32ab0eded163 1a8b605a43ff5bed 8086072ba1e7cc23 58baeca134c825a7])
+)
+
+(assert (=
+ (sha384 (bytes "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))
+ [3391fdddfc8dc739 3707a65b1b470939 7cf8b1d162af05ab fe8f450de5f36bc6 b0455a8520bc4e6f 5fe95b1fe3c8452b])
+)
+
+(assert (=
+ (sha384 (bytes "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))
+ [09330c33f71147e8 3d192fc782cd1b47 53111b173b3b05d2 2fa08086e3b0f712 fcc7c71a557e2db9 66c3e9fa91746039])
+)
+
+(assert (=
+ (sha384 (* (bytes "a") 1000000))
+ [9d0e1809716474cb 086e834e310a4a1c ed149e9c00f24852 7972cec5704c2a5b 07b8b3dc38ecc4eb ae97ddd87f3d8985])
+)
+
+(assert (=
+ (sha384 (bytes "The quick brown fox jumps over the lazy dog"))
+ [ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1])
+)
+
+(assert (=
+ (sha384 (bytes "The quick brown fox jumps over the lazy cog"))
+ [098cea620b0978caa5f0befba6ddcf22764bea977e1c70b3483edfdf1de25f4b40d6cea3cadf00f809d422feb1f0161b])
+)
+
+(assert (=
+ (sha384 [])
+ [38b060a751ac9638 4cd9327eb1b1e36a 21fdb71114be0743 4c0cc7bf63f6e1da 274edebfe76f65fb d51ad2f14898b95b])
+)
+
+(assert (=
+ (hmac-sha384 (* [0b] 20) (bytes "Hi There"))
+ [afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6])
+)
+
+(assert (=
+ (hmac-sha384 (bytes "Jefe") (bytes "what do ya want for nothing?"))
+ [af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649])
+)
+
+(assert (=
+ (hmac-sha384 (* [aa] 20) (* [dd] 50))
+ [88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27])
+)
+
+(assert (=
+ (hmac-sha384 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50))
+ [3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb])
+)
+
+(assert (=
+ (hmac-sha384 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First"))
+ [4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952])
+)
+
+(assert (=
+ (hmac-sha384 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))
+ [6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e])
+)
+
+
+(puts success)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl
new file mode 100644
index 00000000..42010199
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/shitlisp/test-sha512.sl
@@ -0,0 +1,67 @@
+(assert (=
+ (sha512 (bytes "abc"))
+ [ddaf35a193617aba cc417349ae204131 12e6fa4e89a97ea2 0a9eeee64b55d39a 2192992a274fc1a8 36ba3c23a3feebbd 454d4423643ce80e 2a9ac94fa54ca49f])
+)
+
+(assert (=
+ (sha512 (bytes "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"))
+ [204a8fc6dda82f0a 0ced7beb8e08a416 57c16ef468b228a8 279be331a703c335 96fd15c13b1b07f9 aa1d3bea57789ca0 31ad85c7a71dd703 54ec631238ca3445])
+)
+
+(assert (=
+ (sha512 (bytes "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"))
+ [8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909])
+)
+
+(assert (=
+ (sha512 (* (bytes "a") 1000000))
+ [e718483d0ce76964 4e2e42c7bc15b463 8e1f98b13b204428 5632a803afa973eb de0ff244877ea60a 4cb0432ce577c31b eb009c5c2c49aa2e 4eadb217ad8cc09b])
+)
+
+(assert (=
+ (sha512 (bytes "The quick brown fox jumps over the lazy dog"))
+ [07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6])
+)
+
+(assert (=
+ (sha512 (bytes "The quick brown fox jumps over the lazy cog"))
+ [3eeee1d0 e11733ef 152a6c29 503b3ae2 0c4f1f3c da4cb26f 1bc1a41f 91c7fe4a b3bd8649 4049e201 c4bd5155 f31ecb7a 3c860684 3c4cc8df cab7da11 c8ae5045])
+)
+
+(assert (=
+ (sha512 [])
+ [cf83e1357eefb8bd f1542850d66d8007 d620e4050b5715dc 83f4a921d36ce9ce 47d0d13c5d85f2b0 ff8318d2877eec2f 63b931bd47417a81 a538327af927da3e])
+)
+
+(assert (=
+ (hmac-sha512 (* [0b] 20) (bytes "Hi There"))
+ [87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854])
+)
+
+(assert (=
+ (hmac-sha512 (bytes "Jefe") (bytes "what do ya want for nothing?"))
+ [164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737])
+)
+
+(assert (=
+ (hmac-sha512 (* [aa] 20) (* [dd] 50))
+ [fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb])
+)
+
+(assert (=
+ (hmac-sha512 [0102030405060708090a0b0c0d0e0f10111213141516171819] (* [cd] 50))
+ [b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd])
+)
+
+(assert (=
+ (hmac-sha512 (* [aa] 131) (bytes "Test Using Larger Than Block-Size Key - Hash Key First"))
+ [80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598])
+)
+
+(assert (=
+ (hmac-sha512 (* [aa] 131) (bytes "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."))
+ [e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58])
+)
+
+
+(puts success)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/.gitignore b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/.gitignore
new file mode 100644
index 00000000..abc5da36
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/.gitignore
@@ -0,0 +1,15 @@
+*.o
+*.gcov
+*.gcno
+*.gcda
+testaes
+testmodes
+testsha1
+testsha2
+testsha3
+testsalsa20
+testcurve25519
+testpoly1305
+testnorx
+testchacha20poly1305
+testdrbg
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/Makefile b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/Makefile
new file mode 100644
index 00000000..451548d6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/Makefile
@@ -0,0 +1,54 @@
+CFLAGS += -g -O0 -std=gnu99 -fPIC -Wall -Wextra -Werror \
+ -Wno-unused-parameter -Wno-missing-field-initializers
+CPPFLAGS += -I./ext
+
+ifdef WITH_ASAN
+ LDFLAGS += -fsanitize=address
+ CFLAGS += -fsanitize=address
+endif
+
+ifdef WITH_COVERAGE
+ LDFLAGS += -coverage
+ CFLAGS += -coverage
+endif
+
+ifdef WITH_VALGRIND
+ VALGRIND := valgrind --leak-check=full --show-reachable=yes --track-origins=yes
+ TEST_OPT := --no-exec
+endif
+
+TARGETS = testaes testmodes testsha1 testsha2 testsha3 testsalsa20 \
+ testcurve25519 testpoly1305 testnorx testchacha20poly1305 \
+ testdrbg
+all: $(TARGETS)
+
+SOURCES = aes.o sha256.o sha512.o chash.o hmac.o pbkdf2.o modes.o eax.o \
+ gf128.o blockwise.o cmac.o salsa20.o chacha20.o curve25519.o \
+ gcm.o cbcmac.o ccm.o sha3.o sha1.o poly1305.o \
+ norx.o chacha20poly1305.o drbg.o ocb.o
+
+testaes: $(SOURCES) testaes.o
+testmodes: $(SOURCES) testmodes.o
+testsha1: $(SOURCES) testsha1.o
+testsha2: $(SOURCES) testsha2.o
+testsha3: $(SOURCES) testsha3.o
+testsalsa20: $(SOURCES) testsalsa20.o
+testcurve25519: $(SOURCES) testcurve25519.o
+testpoly1305: $(SOURCES) testpoly1305.o
+testnorx: $(SOURCES) testnorx.o
+testchacha20poly1305: $(SOURCES) testchacha20poly1305.o
+testdrbg: $(SOURCES) testdrbg.o
+
+clean:
+ rm -f *.o *.pyc $(TARGETS) *.gcov *.gcda *.gcno
+
+test: $(TARGETS)
+ for x in $(TARGETS) ; do \
+ echo "Running $$x" ; \
+ $(VALGRIND) ./$$x $(TEST_OPT) ; \
+ done
+
+cover: test
+ gcov *.c
+ echo 'Lines with missing coverage:'
+ grep '#####' *.gcov | grep -vE '(cutest|testutil).h.gcov'
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.c
new file mode 100644
index 00000000..545588e5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.c
@@ -0,0 +1,419 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "cf_config.h"
+#include "aes.h"
+#include "handy.h"
+#include "bitops.h"
+#include "tassert.h"
+
+static const uint8_t S[256] =
+{
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,
+ 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4,
+ 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7,
+ 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3,
+ 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09,
+ 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3,
+ 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe,
+ 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92,
+ 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
+ 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
+ 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
+ 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2,
+ 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5,
+ 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25,
+ 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
+ 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,
+ 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42,
+ 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+static const uint8_t Rcon[11] =
+{
+ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
+};
+
+#ifdef INLINE_FUNCS
+static inline uint32_t word4(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
+{
+ return b0 << 24 | b1 << 16 | b2 << 8 | b3;
+}
+
+static inline uint8_t byte(uint32_t w, unsigned x)
+{
+ /* nb. bytes are numbered 0 (leftmost, top)
+ * to 3 (rightmost). */
+ x = 3 - x;
+ return (w >> (x * 8)) & 0xff;
+}
+
+static uint32_t round_constant(uint32_t i)
+{
+ return Rcon[i] << 24;
+}
+
+static uint32_t rot_word(uint32_t w)
+{
+ /* Takes
+ * word [a0,a1,a2,a3]
+ * returns
+ * word [a1,a2,a3,a0]
+ *
+ */
+ return rotl32(w, 8);
+}
+#endif
+
+#define word4(a, b, c, d) (((uint32_t)(a) << 24) | ((uint32_t)(b) << 16) | ((uint32_t)(c) << 8) | (d))
+#define byte(w, x) ((w >> ((3 - (x)) << 3)) & 0xff)
+#define round_constant(i) ((uint32_t)(Rcon[i]) << 24)
+#define rot_word(w) rotl32((w), 8)
+
+static uint32_t sub_word(uint32_t w, const uint8_t *sbox)
+{
+ uint8_t a = byte(w, 0),
+ b = byte(w, 1),
+ c = byte(w, 2),
+ d = byte(w, 3);
+#if CF_CACHE_SIDE_CHANNEL_PROTECTION
+ select_u8x4(&a, &b, &c, &d, sbox, 256);
+#else
+ a = sbox[a];
+ b = sbox[b];
+ c = sbox[c];
+ d = sbox[d];
+#endif
+ return word4(a, b, c, d);
+}
+
+static void aes_schedule(cf_aes_context *ctx, const uint8_t *key, size_t nkey)
+{
+ size_t i,
+ nb = AES_BLOCKSZ / 4,
+ nk = nkey / 4,
+ n = nb * (ctx->rounds + 1);
+ uint32_t *w = ctx->ks;
+
+ /* First words are just the key. */
+ for (i = 0; i < nk; i++)
+ {
+ w[i] = read32_be(key + i * 4);
+ }
+
+ uint32_t i_div_nk = 1;
+ uint32_t i_mod_nk = 0;
+
+ for (; i < n; i++, i_mod_nk++)
+ {
+ uint32_t temp = w[i - 1];
+
+ if (i_mod_nk == nk)
+ {
+ i_div_nk++;
+ i_mod_nk = 0;
+ }
+
+ if (i_mod_nk == 0)
+ temp = sub_word(rot_word(temp), S) ^ round_constant(i_div_nk);
+ else if (nk > 6 && i_mod_nk == 4)
+ temp = sub_word(temp, S);
+
+ w[i] = w[i - nk] ^ temp;
+ }
+}
+
+void cf_aes_init(cf_aes_context *ctx, const uint8_t *key, size_t nkey)
+{
+ memset(ctx, 0, sizeof *ctx);
+
+ switch (nkey)
+ {
+#if CF_AES_MAXROUNDS >= AES128_ROUNDS
+ case 16:
+ ctx->rounds = AES128_ROUNDS;
+ aes_schedule(ctx, key, nkey);
+ break;
+#endif
+
+#if CF_AES_MAXROUNDS >= AES192_ROUNDS
+ case 24:
+ ctx->rounds = AES192_ROUNDS;
+ aes_schedule(ctx, key, nkey);
+ break;
+#endif
+
+#if CF_AES_MAXROUNDS >= AES256_ROUNDS
+ case 32:
+ ctx->rounds = AES256_ROUNDS;
+ aes_schedule(ctx, key, nkey);
+ break;
+#endif
+
+ default:
+ abort();
+ }
+}
+
+static void add_round_key(uint32_t state[4], const uint32_t rk[4])
+{
+ state[0] ^= rk[0];
+ state[1] ^= rk[1];
+ state[2] ^= rk[2];
+ state[3] ^= rk[3];
+}
+
+static void sub_block(uint32_t state[4])
+{
+ state[0] = sub_word(state[0], S);
+ state[1] = sub_word(state[1], S);
+ state[2] = sub_word(state[2], S);
+ state[3] = sub_word(state[3], S);
+}
+
+static void shift_rows(uint32_t state[4])
+{
+ uint32_t u, v, x, y;
+
+ u = word4(byte(state[0], 0),
+ byte(state[1], 1),
+ byte(state[2], 2),
+ byte(state[3], 3));
+
+ v = word4(byte(state[1], 0),
+ byte(state[2], 1),
+ byte(state[3], 2),
+ byte(state[0], 3));
+
+ x = word4(byte(state[2], 0),
+ byte(state[3], 1),
+ byte(state[0], 2),
+ byte(state[1], 3));
+
+ y = word4(byte(state[3], 0),
+ byte(state[0], 1),
+ byte(state[1], 2),
+ byte(state[2], 3));
+
+ state[0] = u;
+ state[1] = v;
+ state[2] = x;
+ state[3] = y;
+}
+
+static uint32_t gf_poly_mul2(uint32_t x)
+{
+ return
+ ((x & 0x7f7f7f7f) << 1) ^
+ (((x & 0x80808080) >> 7) * 0x1b);
+}
+
+static uint32_t mix_column(uint32_t x)
+{
+ uint32_t x2 = gf_poly_mul2(x);
+ return x2 ^ rotr32(x ^ x2, 24) ^ rotr32(x, 16) ^ rotr32(x, 8);
+}
+
+static void mix_columns(uint32_t state[4])
+{
+ state[0] = mix_column(state[0]);
+ state[1] = mix_column(state[1]);
+ state[2] = mix_column(state[2]);
+ state[3] = mix_column(state[3]);
+}
+
+void cf_aes_encrypt(const cf_aes_context *ctx,
+ const uint8_t in[AES_BLOCKSZ],
+ uint8_t out[AES_BLOCKSZ])
+{
+ assert(ctx->rounds == AES128_ROUNDS ||
+ ctx->rounds == AES192_ROUNDS ||
+ ctx->rounds == AES256_ROUNDS);
+
+ uint32_t state[4] = {
+ read32_be(in + 0),
+ read32_be(in + 4),
+ read32_be(in + 8),
+ read32_be(in + 12)
+ };
+
+ const uint32_t *round_keys = ctx->ks;
+ add_round_key(state, round_keys);
+ round_keys += 4;
+
+ uint32_t round;
+ for (round = 1; round < ctx->rounds; round++)
+ {
+ sub_block(state);
+ shift_rows(state);
+ mix_columns(state);
+ add_round_key(state, round_keys);
+ round_keys += 4;
+ }
+
+ sub_block(state);
+ shift_rows(state);
+ add_round_key(state, round_keys);
+
+ write32_be(state[0], out + 0);
+ write32_be(state[1], out + 4);
+ write32_be(state[2], out + 8);
+ write32_be(state[3], out + 12);
+}
+
+#if CF_AES_ENCRYPT_ONLY == 0
+static const uint8_t S_inv[256] =
+{
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,
+ 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e,
+ 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23,
+ 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66,
+ 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,
+ 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,
+ 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46,
+ 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
+ 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,
+ 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91,
+ 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
+ 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
+ 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f,
+ 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2,
+ 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8,
+ 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
+ 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb,
+ 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
+ 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+};
+
+static void inv_sub_block(uint32_t state[4])
+{
+ state[0] = sub_word(state[0], S_inv);
+ state[1] = sub_word(state[1], S_inv);
+ state[2] = sub_word(state[2], S_inv);
+ state[3] = sub_word(state[3], S_inv);
+}
+
+static void inv_shift_rows(uint32_t state[4])
+{
+ uint32_t u, v, x, y;
+
+ u = word4(byte(state[0], 0),
+ byte(state[3], 1),
+ byte(state[2], 2),
+ byte(state[1], 3));
+
+ v = word4(byte(state[1], 0),
+ byte(state[0], 1),
+ byte(state[3], 2),
+ byte(state[2], 3));
+
+ x = word4(byte(state[2], 0),
+ byte(state[1], 1),
+ byte(state[0], 2),
+ byte(state[3], 3));
+
+ y = word4(byte(state[3], 0),
+ byte(state[2], 1),
+ byte(state[1], 2),
+ byte(state[0], 3));
+
+ state[0] = u;
+ state[1] = v;
+ state[2] = x;
+ state[3] = y;
+}
+
+static uint32_t inv_mix_column(uint32_t x)
+{
+ uint32_t x2 = gf_poly_mul2(x),
+ x4 = gf_poly_mul2(x2),
+ x9 = x ^ gf_poly_mul2(x4),
+ x11 = x2 ^ x9,
+ x13 = x4 ^ x9;
+
+ return x ^ x2 ^ x13 ^ rotr32(x11, 24) ^ rotr32(x13, 16) ^ rotr32(x9, 8);
+}
+
+static void inv_mix_columns(uint32_t state[4])
+{
+ state[0] = inv_mix_column(state[0]);
+ state[1] = inv_mix_column(state[1]);
+ state[2] = inv_mix_column(state[2]);
+ state[3] = inv_mix_column(state[3]);
+}
+
+void cf_aes_decrypt(const cf_aes_context *ctx,
+ const uint8_t in[AES_BLOCKSZ],
+ uint8_t out[AES_BLOCKSZ])
+{
+ assert(ctx->rounds == AES128_ROUNDS ||
+ ctx->rounds == AES192_ROUNDS ||
+ ctx->rounds == AES256_ROUNDS);
+
+ uint32_t state[4] = {
+ read32_be(in + 0),
+ read32_be(in + 4),
+ read32_be(in + 8),
+ read32_be(in + 12)
+ };
+
+ const uint32_t *round_keys = &ctx->ks[ctx->rounds << 2];
+ add_round_key(state, round_keys);
+ round_keys -= 4;
+
+ uint32_t round;
+ for (round = ctx->rounds - 1; round != 0; round--)
+ {
+ inv_shift_rows(state);
+ inv_sub_block(state);
+ add_round_key(state, round_keys);
+ inv_mix_columns(state);
+ round_keys -= 4;
+ }
+
+ inv_shift_rows(state);
+ inv_sub_block(state);
+ add_round_key(state, round_keys);
+
+ write32_be(state[0], out + 0);
+ write32_be(state[1], out + 4);
+ write32_be(state[2], out + 8);
+ write32_be(state[3], out + 12);
+}
+#else
+void cf_aes_decrypt(const cf_aes_context *ctx,
+ const uint8_t in[AES_BLOCKSZ],
+ uint8_t out[AES_BLOCKSZ])
+{
+ abort();
+}
+#endif
+
+void cf_aes_finish(cf_aes_context *ctx)
+{
+ mem_clean(ctx, sizeof *ctx);
+}
+
+const cf_prp cf_aes = {
+ .blocksz = AES_BLOCKSZ,
+ .encrypt = (cf_prp_block) cf_aes_encrypt,
+ .decrypt = (cf_prp_block) cf_aes_decrypt
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.h
new file mode 100644
index 00000000..2ee7f467
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/aes.h
@@ -0,0 +1,152 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+/**
+ * The AES block cipher
+ * ====================
+ *
+ * This is a small, simple implementation of AES. Key expansion is done
+ * first, filling in a :c:type:`cf_aes_context`. Then encryption and
+ * decryption can be performed as desired.
+ *
+ * Usually you don't want to use AES directly; you should use it via
+ * a :doc:`block cipher mode <modes>`.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "prp.h"
+
+/* .. c:macro:: AES_BLOCKSZ
+ * AES has a 128-bit block size. This quantity is in bytes.
+ */
+#define AES_BLOCKSZ 16
+
+/* --- Size configuration --- */
+
+/* .. c:macro:: AES128_ROUNDS
+ * .. c:macro:: AES192_ROUNDS
+ * .. c:macro:: AES256_ROUNDS
+ *
+ * Round counts for different key sizes.
+ */
+#define AES128_ROUNDS 10
+#define AES192_ROUNDS 12
+#define AES256_ROUNDS 14
+
+/* .. c:macro:: CF_AES_MAXROUNDS
+ *
+ * You can reduce the maximum number of rounds this implementation
+ * supports. This reduces the storage needed by :c:type:`cf_aes_context`.
+ *
+ * The default is :c:macro:`AES256_ROUNDS` and is good for all key
+ * sizes.
+ */
+#ifndef CF_AES_MAXROUNDS
+# define CF_AES_MAXROUNDS AES256_ROUNDS
+#endif
+
+/* .. c:macro:: CF_AES_ENCRYPT_ONLY
+ *
+ * Define this to 1 if you don't need to decrypt anything.
+ * This saves space. :c:func:`cf_aes_decrypt` calls `abort(3)`.
+ */
+#ifndef CF_AES_ENCRYPT_ONLY
+# define CF_AES_ENCRYPT_ONLY 0
+#endif
+
+/* .. c:type:: cf_aes_context
+ * This type represents an expanded AES key. Create one
+ * using :c:func:`cf_aes_init`, make use of one using
+ * :c:func:`cf_aes_encrypt` or :c:func:`cf_aes_decrypt`.
+ *
+ * The contents of this structure are equivalent to the
+ * original key material. You should clean the
+ * contents of this structure with :c:func:`cf_aes_finish`
+ * when you're done.
+ *
+ * .. c:member:: cf_aes_context.rounds
+ *
+ * Number of rounds to use, set by :c:func:`cf_aes_init`.
+ *
+ * This depends on the original key size, and will be
+ * :c:macro:`AES128_ROUNDS`, :c:macro:`AES192_ROUNDS` or
+ * :c:macro:`AES256_ROUNDS`.
+ *
+ * .. c:member:: cf_aes_context.ks
+ *
+ * Expanded key material. Filled in by :c:func:`cf_aes_init`.
+ */
+typedef struct
+{
+ uint32_t rounds;
+ uint32_t ks[AES_BLOCKSZ / 4 * (CF_AES_MAXROUNDS + 1)];
+} cf_aes_context;
+
+/* .. c:function:: $DECL
+ * This function does AES key expansion. It destroys
+ * existing contents of :c:data:`ctx`.
+ *
+ * :param ctx: expanded key context, filled in by this function.
+ * :param key: pointer to key material, of :c:data:`nkey` bytes.
+ * :param nkey: length of key material. Must be `16`, `24` or `32`.
+ */
+extern void cf_aes_init(cf_aes_context *ctx,
+ const uint8_t *key,
+ size_t nkey);
+
+/* .. c:function:: $DECL
+ * Encrypts the given block, from :c:data:`in` to :c:data:`out`.
+ * These may alias.
+ *
+ * Fails at runtime if :c:data:`ctx` is invalid.
+ *
+ * :param ctx: expanded key context
+ * :param in: input block (read)
+ * :param out: output block (written)
+ */
+extern void cf_aes_encrypt(const cf_aes_context *ctx,
+ const uint8_t in[AES_BLOCKSZ],
+ uint8_t out[AES_BLOCKSZ]);
+
+/* .. c:function:: $DECL
+ * Decrypts the given block, from :c:data:`in` to :c:data:`out`.
+ * These may alias.
+ *
+ * Fails at runtime if :c:data:`ctx` is invalid.
+ *
+ * :param ctx: expanded key context
+ * :param in: input block (read)
+ * :param out: output block (written)
+ */
+extern void cf_aes_decrypt(const cf_aes_context *ctx,
+ const uint8_t in[AES_BLOCKSZ],
+ uint8_t out[AES_BLOCKSZ]);
+
+/* .. c:function:: $DECL
+ * Erase scheduled key material.
+ *
+ * Call this when you're done to erase the round keys. */
+extern void cf_aes_finish(cf_aes_context *ctx);
+
+/* .. c:var:: const cf_prp cf_aes
+ * Abstract interface to AES. See :c:type:`cf_prp` for
+ * more information. */
+extern const cf_prp cf_aes;
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/.gitignore b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/.gitignore
new file mode 100644
index 00000000..5841cb8e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/.gitignore
@@ -0,0 +1,3 @@
+*.log
+*.elf
+*.bin
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/Makefile b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/Makefile
new file mode 100644
index 00000000..7be9a53a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/Makefile
@@ -0,0 +1,184 @@
+FUNCS = do_nothing stack_8w stack_64w \
+ hashtest_sha256 hashtest_sha512 \
+ hashtest_sha3_256 hashtest_sha3_512 \
+ aes128block_test aes128sched_test \
+ aes256block_test aes256sched_test \
+ aes128gcm_test aes128eax_test \
+ aes128ccm_test \
+ salsa20_test chacha20_test \
+ poly1305_test hmacsha256_test \
+ curve25519_test \
+ norx_test
+
+AEADS = aeadperf_aes128gcm \
+ aeadperf_aes128ccm \
+ aeadperf_aes128eax \
+ aeadperf_aes256gcm \
+ aeadperf_aes256ccm \
+ aeadperf_aes256eax \
+ aeadperf_norx \
+ aeadperf_chacha20poly1305
+TESTS = testcurve25519 testaes testmodes testsalsa20 testsha1 testsha2 \
+ testsha3 testpoly1305 testnorx testchacha20poly1305 testdrbg
+ARCHS = stm32f0 stm32f1 stm32f3 efm32 qemucm3
+
+all: $(patsubst %,%.stm32f0.bin,$(FUNCS) $(AEADS) $(TESTS)) \
+ $(patsubst %,%.stm32f1.bin,$(FUNCS) $(AEADS) $(TESTS)) \
+ $(patsubst %,%.stm32f3.bin,$(FUNCS) $(AEADS) $(TESTS)) \
+ $(patsubst %,%.efm32.bin,$(FUNCS) $(AEADS) $(TESTS)) \
+ $(patsubst %,%.qemucm3.bin,$(FUNCS) $(AEADS) $(TESTS))
+
+%.stm32f0.elf:
+ arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.stm32f0.ld -mcpu=cortex-m0 -DCORTEX_M0 -o $@ $^ -DTEST=$* -lgcc
+
+%.stm32f1.elf:
+ arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.stm32f1.ld -mcpu=cortex-m3 -DCORTEX_M3 -o $@ $^ -DTEST=$* -lgcc
+
+%.stm32f3.elf:
+ arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.stm32f3.ld -mcpu=cortex-m4 -DCORTEX_M4 -o $@ $^ -DTEST=$* -lgcc
+
+%.efm32.elf:
+ arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.efm32.ld -mcpu=cortex-m0 -DCORTEX_M0 -o $@ $^ -DTEST=$* -lgcc
+
+%.qemucm3.elf:
+ arm-none-eabi-gcc $(CFLAGS) $(CFLAGS_$*) $(LDFLAGS) -T linkscript.qemucm3.ld -mcpu=cortex-m3 -DCORTEX_M3 -o $@ $^ -DTEST=$* -lgcc
+
+%.bin: %.elf
+ arm-none-eabi-objcopy -O binary $< $@
+.PRECIOUS: %.bin
+
+AES_OPTIONS = -DCF_AES_ENCRYPT_ONLY=1 -DCF_SIDE_CHANNEL_PROTECTION=0
+AES128_OPTIONS = -DCF_AES_MAXROUNDS=AES128_ROUNDS
+AES256_OPTIONS = -DCF_AES_MAXROUNDS=AES256_ROUNDS
+
+AEADPERF_BRACKET = -DBRACKET_MODE=1 -DBRACKET_START=0 -DBRACKET_END=256 -DBRACKET_STEP=4
+
+CFLAGS_aes128block_test = $(AES_OPTIONS) $(AES128_OPTIONS)
+CFLAGS_aes128sched_test = $(AES_OPTIONS) $(AES128_OPTIONS)
+CFLAGS_aes128gcm_test = $(AES_OPTIONS) $(AES128_OPTIONS)
+CFLAGS_aes128eax_test = $(AES_OPTIONS) $(AES128_OPTIONS)
+CFLAGS_aes128ccm_test = $(AES_OPTIONS) $(AES128_OPTIONS)
+CFLAGS_poly1305_test = $(AES_OPTIONS) $(AES128_OPTIONS)
+
+CFLAGS_aeadperf_aes128gcm = $(AES_OPTIONS) $(AES128_OPTIONS) $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_aes128eax = $(AES_OPTIONS) $(AES128_OPTIONS) $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_aes128ccm = $(AES_OPTIONS) $(AES128_OPTIONS) $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_aes256gcm = $(AES_OPTIONS) $(AES256_OPTIONS) $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_aes256eax = $(AES_OPTIONS) $(AES256_OPTIONS) $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_aes256ccm = $(AES_OPTIONS) $(AES256_OPTIONS) $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_norx = $(AEADPERF_BRACKET)
+CFLAGS_aeadperf_chacha20poly1305 = $(AEADPERF_BRACKET)
+
+CFLAGS_aes256block_test = $(AES_OPTIONS) $(AES256_OPTIONS)
+CFLAGS_aes256sched_test = $(AES_OPTIONS) $(AES256_OPTIONS)
+
+CFLAGS_testaes = -DCF_SIDE_CHANNEL_PROTECTION=0
+
+CFLAGS = -I./ext -I../ext -I.. -Os -ffunction-sections -g \
+ -Wall -Werror -std=gnu99 -mthumb
+LDFLAGS = -nostartfiles -nostdlib -Wl,-gc-sections
+CURVESRCS = unacl/cortex_m0_mpy121666.s unacl/cortex_m0_reduce25519.s unacl/mul.s unacl/sqr.s
+SRCS = boot.c memcpy.s memset.s semihost.c semihost.s \
+ ../sha1.c ../sha256.c ../sha512.c ../sha3.c ../blockwise.c ../chash.c \
+ ../curve25519.c ../poly1305.c \
+ ../aes.c ../eax.c ../gcm.c ../cbcmac.c ../ccm.c \
+ ../modes.c ../cmac.c ../gf128.c \
+ ../hmac.c ../pbkdf2.c ../salsa20.c ../chacha20.c \
+ ../norx.c ../chacha20poly1305.c ../drbg.c
+
+$(patsubst %,%.stm32f0.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS)
+$(patsubst %,%.stm32f1.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS)
+$(patsubst %,%.stm32f3.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS)
+$(patsubst %,%.efm32.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS)
+$(patsubst %,%.qemucm3.elf, $(FUNCS) $(AEADS)): $(SRCS) main.c $(CURVESRCS)
+
+$(patsubst %,testcurve25519.%.elf, $(ARCHS)): $(SRCS) $(CURVESRCS) ../testcurve25519.c
+$(patsubst %,testaes.%.elf, $(ARCHS)): $(SRCS) ../testaes.c
+$(patsubst %,testmodes.%.elf, $(ARCHS)): $(SRCS) ../testmodes.c
+$(patsubst %,testsalsa20.%.elf, $(ARCHS)): $(SRCS) ../testsalsa20.c
+$(patsubst %,testsha1.%.elf, $(ARCHS)): $(SRCS) ../testsha1.c
+$(patsubst %,testsha2.%.elf, $(ARCHS)): $(SRCS) ../testsha2.c
+$(patsubst %,testsha3.%.elf, $(ARCHS)): $(SRCS) ../testsha3.c
+$(patsubst %,testpoly1305.%.elf, $(ARCHS)): $(SRCS) ../testpoly1305.c
+$(patsubst %,testnorx.%.elf, $(ARCHS)): $(SRCS) ../testnorx.c
+$(patsubst %,testchacha20poly1305.%.elf, $(ARCHS)): $(SRCS) ../testchacha20poly1305.c
+$(patsubst %,testdrbg.%.elf, $(ARCHS)): $(SRCS) ../testdrbg.c
+
+run.%.qemucm3: %.qemucm3.bin
+ arm-none-eabi-readelf -l $(patsubst %.bin,%.elf,$^) > $@.log
+ qemu-system-gnuarmeclipse -verbose -verbose -M STM32-P103 -kernel $^ -semihosting -nographic -monitor null -serial null 2>> $@.log
+ cat $@.log
+
+run.%.efm32: %.efm32.elf
+ arm-none-eabi-readelf -l $^ > $@.log
+ echo '-----' >> $@.log
+ openocd -f openocd.efm32.cfg >> $@.log &
+ arm-none-eabi-gdb --quiet --batch-silent \
+ $^ \
+ -ex 'target remote :3333' \
+ -ex 'monitor reset halt' \
+ -ex 'load' \
+ -ex 'monitor arm semihosting enable' \
+ -ex 'monitor reset run' \
+ -ex 'monitor wait_halt 720000' \
+ -ex 'monitor shutdown'
+
+run.%.stm32f0: %.stm32f0.elf
+ arm-none-eabi-readelf -l $^ > $@.log
+ echo '-----' >> $@.log
+ openocd -f openocd.stm32f0.cfg >> $@.log &
+ arm-none-eabi-gdb --quiet --batch-silent \
+ $^ \
+ -ex 'target remote :3333' \
+ -ex 'monitor reset halt' \
+ -ex 'load' \
+ -ex 'monitor arm semihosting enable' \
+ -ex 'monitor reset run' \
+ -ex 'monitor wait_halt 720000' \
+ -ex 'monitor shutdown'
+
+run.%.stm32f1: %.stm32f1.elf
+ arm-none-eabi-readelf -l $^ > $@.log
+ echo '-----' >> $@.log
+ openocd -f openocd.stm32f1.cfg >> $@.log &
+ arm-none-eabi-gdb --quiet --batch-silent \
+ $^ \
+ -ex 'target remote :3333' \
+ -ex 'monitor reset halt' \
+ -ex 'load' \
+ -ex 'monitor arm semihosting enable' \
+ -ex 'monitor reset run' \
+ -ex 'monitor wait_halt 720000' \
+ -ex 'monitor shutdown'
+
+run.%.stm32f3: %.stm32f3.elf
+ arm-none-eabi-readelf -l $^ > $@.log
+ echo '-----' >> $@.log
+ openocd -f openocd.stm32f3.cfg >> $@.log &
+ arm-none-eabi-gdb --quiet --batch-silent \
+ $^ \
+ -ex 'target remote :3333' \
+ -ex 'monitor reset halt' \
+ -ex 'load' \
+ -ex 'monitor arm semihosting enable' \
+ -ex 'monitor reset run' \
+ -ex 'monitor wait_halt 720000' \
+ -ex 'monitor shutdown'
+
+test: $(patsubst %,run.%.qemucm3,$(FUNCS) $(TESTS))
+.PHONY: test
+
+perf.stm32f0: $(patsubst %,run.%.stm32f0,$(FUNCS))
+.PHONY: perf.stm32f0
+
+test.stm32f0: $(patsubst %,run.%.stm32f0,$(FUNCS) $(TESTS))
+.PHONY: test.stm32f0
+
+test.stm32f1: $(patsubst %,run.%.stm32f1,$(FUNCS) $(TESTS))
+.PHONY: test.stm32f1
+
+test.stm32f3: $(patsubst %,run.%.stm32f3,$(FUNCS) $(TESTS))
+.PHONY: test.stm32f3
+
+clean:
+ rm -rf *.log *.elf *.bin
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/analyse.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/analyse.py
new file mode 100644
index 00000000..d2c456fe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/analyse.py
@@ -0,0 +1,207 @@
+import subprocess
+import sys
+import re
+
+function_intro_re = re.compile(r'^(?P<addr>[0-9a-fA-F]{8}) <(?P<name>[a-zA-Z0-9\._]+)>:$')
+insn_re = re.compile(r'^\s+(?P<addr>[0-9a-fA-F]+):\s+(?P<insn>[0-9a-fA-F ]+)\s+\t(?P<op>.*)$')
+
+class Instruction:
+ def __init__(self, addr, insn, op):
+ self.addr = long(addr, 16)
+ self.insn = insn
+
+ args = op.split('\t', 1)
+
+ self.op = args[0].strip()
+ if len(args) == 2:
+ comment = args[1].strip().split(';', 1)
+ else:
+ comment = args
+
+ self.args = comment[0].strip()
+
+ if len(comment) == 2:
+ self.comment = comment[1].strip()
+ else:
+ self.comment = ''
+
+ def __repr__(self):
+ return '<insn %r>' % (self.__dict__)
+
+
+def literal_branch_target(t):
+ return ' <' in t
+
+class Function:
+ def __init__(self, addr, name):
+ self.name = name
+ self.addr = long(addr, 16)
+ self.insns = []
+ self.calls = []
+
+ def __repr__(self):
+ return '<%s %d instructions>' % (self.name, len(self.insns))
+
+ def add_insn(self, insn):
+ self.insns.append(Instruction(**insn))
+
+ def contains_addr(self, addr):
+ if self.insns:
+ return addr >= self.addr and addr <= self.insns[-1].addr
+ else:
+ return addr == self.addr
+
+ def dump(self):
+ print self.name + ':'
+ for insn in self.insns:
+ print ' ', '%04x' % insn.addr + ':', insn.op, insn.args, '\t;', insn.comment
+
+ def get_literal_word(self, addr):
+ for insn in self.insns:
+ if insn.addr == addr and insn.op == '.word':
+ w = int(insn.args, 16)
+ if w & 0x80000000:
+ w = -(w ^ 0xffffffff) + 1
+ return w
+ return None
+
+ def analyse(self, prog):
+ self.stack_guess = None
+ regs = {}
+
+ for insn in self.insns:
+ # stack adjustment with literal
+ if insn.op == 'sub' and insn.args.startswith('sp, ') and self.stack_guess is None:
+ sz = int(insn.args.split('#', 1)[1])
+ self.stack_guess = sz
+
+ # literal pool loads
+ if insn.op == 'ldr' and ', [pc, #' in insn.args:
+ reg, offset = insn.args.split(', [pc, #')
+ offset = int(offset.replace(']', ''))
+ word = self.get_literal_word(insn.addr + offset + 2)
+ if word is not None:
+ regs[reg] = word
+
+ if insn.op == 'add' and insn.args.startswith('sp, r') and self.stack_guess is None:
+ reg = insn.args.split(', ')[1]
+ if reg in regs:
+ self.stack_guess = regs[reg]
+
+ # static branches
+ if insn.op[0] == 'b' and literal_branch_target(insn.args):
+ target = long(insn.args.split(' <', 1)[0], 16)
+
+ targetf = prog.function_at_addr(target)
+
+ if targetf and targetf != self:
+ self.calls.append(targetf)
+
+ if self.stack_guess is None:
+ self.stack_guess = 0
+
+ def stack_usage(self, hints, warns, prog, depth = 0):
+ hinted_calls = []
+ if self.stack_guess:
+ print ' ' * depth, 'stack:', self.name, self.stack_guess, 'bytes'
+
+ our_hints = [h for h in hints if h and h[0] == self.name]
+ if our_hints:
+ hints = [h[1:] for h in our_hints]
+ hinted_calls = [prog.function_by_name(h[0]) for h in hints if h]
+ else:
+ if self.name in warns:
+ print ' WARN: no calls hints for fn-ptr caller', self.name
+
+ if self.calls + hinted_calls:
+ call_usage = max([f.stack_usage(hints, warns, prog, depth + 1) for f in self.calls + hinted_calls])
+ else:
+ call_usage = 0
+ return self.stack_guess + call_usage
+
+class Program:
+ def __init__(self):
+ self.functions = []
+
+ # sequence of tuples naming a call sequence known to occur
+ # this allows working out calls through pointers
+ self.call_hints = []
+
+ # function names to warn on if we don't have callees
+ self.call_warns = set()
+
+ def read_elf(self, elf):
+ current_fn = None
+
+ for x in subprocess.Popen(['arm-none-eabi-objdump', '-d', elf],
+ stdout = subprocess.PIPE).stdout:
+ x = x.rstrip('\n')
+ m = function_intro_re.match(x)
+ if m:
+ fn = Function(**m.groupdict())
+ current_fn = fn
+ self.functions.append(fn)
+
+ m = insn_re.match(x)
+ if m:
+ assert current_fn
+ current_fn.add_insn(m.groupdict())
+
+ def analyse(self):
+ for f in self.functions:
+ f.analyse(self)
+
+ def function_by_name(self, name):
+ fns = [fn for fn in self.functions if fn.name == name]
+ if len(fns) == 0:
+ return None
+ elif len(fns) == 1:
+ return fns[0]
+ else:
+ print 'warn: more than one function named', name
+ return None
+
+ def function_at_addr(self, addr):
+ for f in self.functions:
+ if f.addr == addr:
+ return f
+ return None
+
+ def add_call_hint(self, *seq):
+ self.call_hints.append(seq)
+
+ def add_call_warn(self, fn):
+ self.call_warns.add(fn)
+
+ def measure_stack(self, name):
+ fn = self.function_by_name(name)
+ if fn is None:
+ return 0
+
+ return fn.stack_usage(self.call_hints, self.call_warns, self)
+
+_, exe, fn = sys.argv
+
+p = Program()
+p.read_elf(exe)
+
+p.analyse()
+
+# calls which indirect through fn ptrs
+p.add_call_warn('cf_blockwise_accumulate')
+p.add_call_warn('cf_blockwise_accumulate_final')
+
+# hints to resolve those
+p.add_call_hint('cf_sha224_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha256_update_block')
+p.add_call_hint('cf_sha256_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha256_update_block')
+p.add_call_hint('cf_sha384_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha512_update_block')
+p.add_call_hint('cf_sha512_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'sha512_update_block')
+p.add_call_hint('cf_norx32_encrypt', 'input', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'input_block')
+p.add_call_hint('cf_norx32_decrypt', 'input', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'input_block')
+p.add_call_hint('cf_cbcmac_stream_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'cbcmac_process')
+p.add_call_hint('cf_cmac_stream_update', 'cf_blockwise_accumulate', 'cf_blockwise_accumulate_final', 'cmac_process_final_pad')
+p.add_call_hint('cf_cmac_stream_update', 'cf_blockwise_accumulate_final', 'cmac_process')
+p.add_call_hint('cf_cmac_stream_update', 'cf_blockwise_accumulate_final', 'cmac_process_final_nopad')
+
+
+print 'stack', fn, '=', p.measure_stack(fn)
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/boot.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/boot.c
new file mode 100644
index 00000000..d2a8e407
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/boot.c
@@ -0,0 +1,144 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern int main(void);
+
+/* --- Defined by link script --- */
+extern uint32_t __etext; /* End of text/start of data. */
+extern uint32_t __data_start__, __data_end__; /* Data addresses in RAM */
+extern uint32_t __bss_start__, __bss_end__; /* BSS addresses in RAM */
+extern uint32_t __StackTop; /* End of stack in RAM */
+
+#define ATTR_SECTION(sec) __attribute__ ((section (sec)))
+
+/* --- Interrupt vector table. --- */
+void Reset_Handler(void);
+void SysTick_Handler(void);
+void infinite_loop(void);
+void do_nothing(void);
+
+typedef void (*vector_fn)(void);
+
+typedef struct {
+ uint32_t *stack_top;
+ vector_fn reset, nmi, hard_fault, mmu_fault, bus_fault, usage_fault;
+ vector_fn reserved0[4];
+ vector_fn svc, debug_monitor;
+ vector_fn reserved1;
+ vector_fn pendsv, systick;
+ vector_fn irq[128];
+} vectors_t;
+
+#define COPY2(v) v, v
+#define COPY4(v) COPY2(v), COPY2(v)
+#define COPY8(v) COPY4(v), COPY4(v)
+#define COPY16(v) COPY8(v), COPY8(v)
+#define COPY32(v) COPY16(v), COPY16(v)
+#define COPY64(v) COPY32(v), COPY32(v)
+#define COPY128(v) COPY64(v), COPY64(v)
+
+vectors_t vectors ATTR_SECTION(".isr_vector") = {
+ .stack_top = &__StackTop,
+ .reset = Reset_Handler,
+ .nmi = do_nothing,
+ .hard_fault = infinite_loop,
+ .mmu_fault = infinite_loop,
+ .bus_fault = infinite_loop,
+ .usage_fault = infinite_loop,
+ .svc = do_nothing,
+ .debug_monitor = do_nothing,
+ .pendsv = do_nothing,
+ .systick = SysTick_Handler,
+ .irq = { COPY128(do_nothing) }
+};
+
+/* --- ISRs --- */
+void Reset_Handler(void)
+{
+ /* Copy data segment contents from flash to RAM. */
+ uint32_t data_bytes = (&__data_end__ - &__data_start__) * 4;
+ memcpy(&__etext, &__data_start__, data_bytes);
+
+ /* Zero BSS. */
+ uint32_t bss_bytes = (&__bss_end__ - &__bss_start__) * 4;
+ memset(&__bss_start__, 0, bss_bytes);
+
+ main();
+ while (1)
+ ;
+}
+
+void __assert_func(const char *file, int line, const char *func, const char *expr)
+{
+ while (1)
+ ;
+}
+
+void infinite_loop(void)
+{
+ while (1)
+ ;
+}
+
+void do_nothing(void)
+{
+}
+
+uint32_t ticks = 0;
+
+void SysTick_Handler(void)
+{
+ ticks++;
+}
+
+uint32_t get_ticks(void)
+{
+ return ticks;
+}
+
+void reset_ticks(void)
+{
+ ticks = 0;
+}
+
+void *memmove(void *vtarg, const void *vsrc, size_t len)
+{
+ if (vsrc > vtarg)
+ return memcpy(vtarg, vsrc, len);
+ else if (vsrc == vtarg)
+ return vtarg;
+
+ uint8_t *targ = vtarg;
+ const uint8_t *src = vsrc;
+
+ for (size_t i = len; i != 0; i++)
+ targ[i - 1] = src[i - 1];
+ return vtarg;
+}
+
+int memcmp(const void *va, const void *vb, size_t len)
+{
+ const uint8_t *a = va, *b = vb;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ if (a[i] != b[i])
+ return a[i] < b[i] ? -1 : 1;
+ }
+
+ return 0;
+}
+
+size_t strlen(const char *c)
+{
+ size_t r = 0;
+ while (*c++) r++;
+ return r;
+}
+
+void abort(void)
+{
+ while (1)
+ ;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt
new file mode 100644
index 00000000..968e40e5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/curve25519-results.txt
@@ -0,0 +1,22 @@
+STM32F0
+donna-before-opt: 12907000c
+donna-after-opt: 17294000c
+donna-reset-opt: 12947000c
+~20k
+
+donna -O2 -Os: 15268000c
+donna -O2 -Os noasm: 20453000c
+donna -Os: 15748000c
+7.4k
+
+donna -O3: 12907000c 16KB 3380b
+donna -Os: 15748000c 7.4KB 3148b
+donna -O2: 15218000c 7.9KB 3148b
+
+tweetnacl -O2: 68876000c 3.0KB 2268b
+tweetnacl -Os: 75979000c 2.8KB 2244b
+tweetnacl -O3: 69622000c 8.9KB 2900b
+
+naclref -Os: 47813000c 3.2KB 4012b
+naclref -O3: 35059000c 4.1KB 4044b
+naclref -O2: 34309000c 3.5KB 4036b
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h
new file mode 100644
index 00000000..fa3c5d84
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/ext/cutest.h
@@ -0,0 +1,55 @@
+/* cutest, for embedded targets. */
+
+#ifndef CUTEST_H
+#define CUTEST_H
+
+/* Main interface. */
+#define TEST_LIST const struct test__ test_list__[]
+#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, #cond)
+/* no TEST_CHECK_ -- we don't have a good enough printf */
+
+/* Implementation */
+#include "../semihost.h"
+
+struct test__
+{
+ const char *name;
+ void (*func)(void);
+};
+
+extern const struct test__ test_list__[];
+
+static void test_check__(int cond, const char *file, int line, const char *expr)
+{
+ if (cond)
+ return; /* pass */
+
+ emit("Failed!\n");
+ emit("File: "); emit(file); emit("\n");
+ emit("Line: "); emit_uint32(line); emit("\n");
+ emit("Expr: "); emit(expr); emit("\n");
+ quit_failure();
+}
+
+static void run_test__(const struct test__ *t)
+{
+ emit(" "); emit(t->name); emit(": ");
+ t->func();
+ emit("OK\n");
+}
+
+int main(void)
+{
+ emit("Running tests:\n");
+
+ for (const struct test__ *t = test_list__;
+ t->name;
+ t++)
+ {
+ run_test__(t);
+ }
+ emit("Success\n");
+ quit_success();
+}
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld
new file mode 100644
index 00000000..8b9a6bfd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.efm32.ld
@@ -0,0 +1,8 @@
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+INCLUDE linkscript.std.ld
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld
new file mode 100644
index 00000000..14fdac4e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.lm3s6965evb.ld
@@ -0,0 +1,7 @@
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
+}
+
+INCLUDE linkscript.std.ld
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld
new file mode 100644
index 00000000..28264674
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.qemucm3.ld
@@ -0,0 +1,8 @@
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 128K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
+}
+
+INCLUDE linkscript.std.ld
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld
new file mode 100644
index 00000000..c08d7bea
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.std.ld
@@ -0,0 +1,172 @@
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ * Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ * __exidx_start
+ * __exidx_end
+ * __copy_table_start__
+ * __copy_table_end__
+ * __zero_table_start__
+ * __zero_table_end__
+ * __etext
+ * __data_start__
+ * __preinit_array_start
+ * __preinit_array_end
+ * __init_array_start
+ * __init_array_end
+ * __fini_array_start
+ * __fini_array_end
+ * __data_end__
+ * __bss_start__
+ * __bss_end__
+ * __end__
+ * end
+ * __HeapLimit
+ * __StackLimit
+ * __StackTop
+ * __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+ .text :
+ {
+ KEEP(*(.isr_vector))
+ *(.text*)
+
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ /* .ctors */
+ *crtbegin.o(.ctors)
+ *crtbegin?.o(.ctors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+ *(SORT(.ctors.*))
+ *(.ctors)
+
+ /* .dtors */
+ *crtbegin.o(.dtors)
+ *crtbegin?.o(.dtors)
+ *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ *(SORT(.dtors.*))
+ *(.dtors)
+
+ *(.rodata*)
+
+ KEEP(*(.eh_frame*))
+ } > FLASH
+
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } > FLASH
+
+ __exidx_start = .;
+ .ARM.exidx :
+ {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } > FLASH
+ __exidx_end = .;
+
+ /* To copy multiple ROM to RAM sections,
+ * uncomment .copy.table section and,
+ * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+
+ .copy.table :
+ {
+ . = ALIGN(4);
+ __copy_table_start__ = .;
+ LONG (__etext)
+ LONG (__data_start__)
+ LONG (__data_end__ - __data_start__)
+ __copy_table_end__ = .;
+ } > FLASH
+
+
+ /* To clear multiple BSS sections,
+ * uncomment .zero.table section and,
+ * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+ .zero.table :
+ {
+ . = ALIGN(4);
+ __zero_table_start__ = .;
+ LONG (__bss_start__)
+ LONG (__bss_end__ - __bss_start__)
+ __zero_table_end__ = .;
+ } > FLASH
+
+ __etext = .;
+
+ .data : AT (__etext)
+ {
+ __data_start__ = .;
+ *(vtable)
+ *(.data*)
+
+ . = ALIGN(4);
+ /* preinit data */
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP(*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+
+ . = ALIGN(4);
+ /* init data */
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+
+
+ . = ALIGN(4);
+ /* finit data */
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+
+ KEEP(*(.jcr*))
+ . = ALIGN(4);
+ /* All data end */
+ __data_end__ = .;
+
+ } > RAM
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start__ = .;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } > RAM
+
+ .heap (COPY):
+ {
+ __end__ = .;
+ PROVIDE(end = .);
+ *(.heap*)
+ __HeapLimit = .;
+ } > RAM
+
+ /* .stack_dummy section doesn't contains any symbols. It is only
+ * used for linker to calculate size of stack sections, and assign
+ * values to stack symbols later */
+ .stack_dummy (COPY):
+ {
+ *(.stack*)
+ } > RAM
+
+ /* Set stack top to end of RAM, and stack limit move down by
+ * size of stack_dummy section */
+ __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+ PROVIDE(__stack = __StackTop);
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld
new file mode 100644
index 00000000..c7a3bd85
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f0.ld
@@ -0,0 +1,8 @@
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
+}
+
+INCLUDE linkscript.std.ld
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld
new file mode 100644
index 00000000..d13f58de
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f1.ld
@@ -0,0 +1,8 @@
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+INCLUDE linkscript.std.ld
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld
new file mode 100644
index 00000000..92eee46e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/linkscript.stm32f3.ld
@@ -0,0 +1,8 @@
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
+ RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 12K
+}
+
+INCLUDE linkscript.std.ld
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/main.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/main.c
new file mode 100644
index 00000000..5b7cbf22
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/main.c
@@ -0,0 +1,447 @@
+#ifndef TEST
+# error You must select a function to test.
+#endif
+
+#include "semihost.h"
+#include "aes.h"
+#include "hmac.h"
+#include "sha2.h"
+#include "sha3.h"
+#include "modes.h"
+#include "salsa20.h"
+#include "curve25519.h"
+#include "poly1305.h"
+#include "norx.h"
+#include "chacha20poly1305.h"
+
+#include <stdio.h>
+
+typedef void (*measure_fn)(void);
+static uint32_t bracket; /* bracket mode parameter */
+
+static void do_nothing(void)
+{
+}
+
+static void stack_64w(void)
+{
+ volatile uint32_t words[64];
+ words[0] = 0;
+ words[63] = 0;
+ (void) words[63];
+}
+
+static void stack_8w(void)
+{
+ volatile uint32_t words[8];
+ words[0] = 0;
+ words[7] = 0;
+ (void) words[7];
+}
+
+static void hashtest_sha256(void)
+{
+ uint8_t hash[CF_SHA256_HASHSZ];
+ cf_sha256_context ctx;
+ cf_sha256_init(&ctx);
+ cf_sha256_update(&ctx, "", 0);
+ cf_sha256_digest_final(&ctx, hash);
+}
+
+static void hashtest_sha512(void)
+{
+ uint8_t hash[CF_SHA512_HASHSZ];
+ cf_sha512_context ctx;
+ cf_sha512_init(&ctx);
+ cf_sha512_update(&ctx, "", 0);
+ cf_sha512_digest_final(&ctx, hash);
+}
+
+static void hashtest_sha3_256(void)
+{
+ uint8_t hash[CF_SHA3_256_HASHSZ];
+ cf_sha3_context ctx;
+ cf_sha3_256_init(&ctx);
+ cf_sha3_256_update(&ctx, "", 0);
+ cf_sha3_256_digest_final(&ctx, hash);
+}
+
+static void hashtest_sha3_512(void)
+{
+ uint8_t hash[CF_SHA3_512_HASHSZ];
+ cf_sha3_context ctx;
+ cf_sha3_512_init(&ctx);
+ cf_sha3_512_update(&ctx, "", 0);
+ cf_sha3_512_digest_final(&ctx, hash);
+}
+
+static void aes128block_test(void)
+{
+ uint8_t key[16] = { 0 }, block[16] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+ cf_aes_encrypt(&ctx, block, block);
+}
+
+static void aes128sched_test(void)
+{
+ uint8_t key[16] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+}
+
+static void aes256block_test(void)
+{
+ uint8_t key[32] = { 0 }, block[16] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+ cf_aes_encrypt(&ctx, block, block);
+}
+
+static void aes256sched_test(void)
+{
+ uint8_t key[32] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+}
+
+static void aes128gcm_test(void)
+{
+ uint8_t key[16] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+
+ uint8_t msg[16] = { 0 };
+ uint8_t aad[16] = { 0 };
+ uint8_t nonce[12] = { 0 };
+ uint8_t cipher[16] = { 0 };
+ uint8_t tag[16] = { 0 };
+
+ cf_gcm_encrypt(&cf_aes, &ctx,
+ msg, sizeof msg,
+ aad, sizeof aad,
+ nonce, sizeof nonce,
+ cipher,
+ tag, sizeof tag);
+}
+
+static void aes128eax_test(void)
+{
+ uint8_t key[16] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+
+ uint8_t msg[16] = { 0 };
+ uint8_t aad[16] = { 0 };
+ uint8_t nonce[12] = { 0 };
+ uint8_t cipher[16] = { 0 };
+ uint8_t tag[16] = { 0 };
+
+ cf_eax_encrypt(&cf_aes, &ctx,
+ msg, sizeof msg,
+ aad, sizeof aad,
+ nonce, sizeof nonce,
+ cipher,
+ tag, sizeof tag);
+}
+
+static void aes128ccm_test(void)
+{
+ uint8_t key[16] = { 0 };
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+
+ uint8_t msg[16] = { 0 };
+ uint8_t aad[16] = { 0 };
+ uint8_t nonce[11] = { 0 };
+ uint8_t cipher[16] = { 0 };
+ uint8_t tag[16] = { 0 };
+
+ cf_ccm_encrypt(&cf_aes, &ctx,
+ msg, sizeof msg, 4,
+ aad, sizeof aad,
+ nonce, sizeof nonce,
+ cipher,
+ tag, sizeof tag);
+}
+
+static void salsa20_test(void)
+{
+ uint8_t key[32] = { 0 };
+ uint8_t nonce[8] = { 0 };
+ uint8_t msg[64] = { 0 };
+ uint8_t cipher[64] = { 0 };
+
+ cf_salsa20_ctx ctx;
+ cf_salsa20_init(&ctx, key, sizeof key, nonce);
+ cf_salsa20_cipher(&ctx, msg, cipher, sizeof msg);
+}
+
+static void chacha20_test(void)
+{
+ uint8_t key[32] = { 0 };
+ uint8_t nonce[8] = { 0 };
+ uint8_t msg[64] = { 0 };
+ uint8_t cipher[64] = { 0 };
+
+ cf_chacha20_ctx ctx;
+ cf_chacha20_init(&ctx, key, sizeof key, nonce);
+ cf_chacha20_cipher(&ctx, msg, cipher, sizeof msg);
+}
+
+static void curve25519_test(void)
+{
+ uint8_t secret[32] = { 1 };
+ uint8_t pubkey[32];
+ cf_curve25519_mul_base(pubkey, secret);
+}
+
+static const uint8_t *mac_message = (const uint8_t *) "hello world";
+static const size_t mac_message_len = 11;
+
+static void poly1305_test(void)
+{
+ uint8_t key[32] = { 0 },
+ nonce[16] = { 0 },
+ encnonce[16],
+ mac[16];
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, key, 16);
+ cf_aes_encrypt(&aes, nonce, encnonce);
+
+ cf_poly1305 poly;
+ cf_poly1305_init(&poly, key + 16, encnonce);
+ cf_poly1305_update(&poly, mac_message, mac_message_len);
+ cf_poly1305_finish(&poly, mac);
+}
+
+static void hmacsha256_test(void)
+{
+ uint8_t key[32] = { 0 },
+ mac[32] = { 0 };
+
+ cf_hmac_ctx ctx;
+ cf_hmac_init(&ctx, &cf_sha256, key, sizeof key);
+ cf_hmac_update(&ctx, mac_message, mac_message_len);
+ cf_hmac_finish(&ctx, mac);
+}
+
+static void norx_test(void)
+{
+ uint8_t key[16] = { 0 };
+ uint8_t msg[16] = { 0 };
+ uint8_t aad[16] = { 0 };
+ uint8_t nonce[8] = { 0 };
+ uint8_t cipher[16] = { 0 };
+ uint8_t tag[16] = { 0 };
+
+ cf_norx32_encrypt(key,
+ nonce,
+ aad, sizeof aad,
+ msg, sizeof msg,
+ NULL, 0,
+ cipher,
+ tag);
+}
+
+#ifndef BRACKET_MODE
+# define AEADPERF_LEN 1
+#else
+# define AEADPERF_LEN BRACKET_END
+#endif
+
+static uint8_t aead_msg[AEADPERF_LEN] = { 0 };
+static uint8_t aead_cipher[AEADPERF_LEN] = { 0 };
+static uint8_t aead_aad[16] = { 0 };
+static uint8_t aead_key[32] = { 0 };
+static uint8_t aead_nonce[16] = { 0 };
+static uint8_t aead_tag[16] = { 0 };
+
+static void aeadperf_norx(void)
+{
+ cf_norx32_encrypt(aead_key, aead_nonce,
+ aead_aad, sizeof aead_aad,
+ aead_msg, bracket,
+ NULL, 0,
+ aead_cipher, aead_tag);
+}
+
+static void aeadperf_chacha20poly1305(void)
+{
+ cf_chacha20poly1305_encrypt(aead_key, aead_nonce,
+ aead_aad, sizeof aead_aad,
+ aead_msg, bracket,
+ aead_cipher, aead_tag);
+}
+static void aeadperf_aes128gcm(void)
+{
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, aead_key, 16);
+
+ cf_gcm_encrypt(&cf_aes, &ctx,
+ aead_msg, bracket,
+ aead_aad, sizeof aead_aad,
+ aead_nonce, 12,
+ aead_cipher,
+ aead_tag, 16);
+}
+
+static void aeadperf_aes128ccm(void)
+{
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, aead_key, 16);
+
+ cf_ccm_encrypt(&cf_aes, &ctx,
+ aead_msg, bracket,
+ 4,
+ aead_aad, sizeof aead_aad,
+ aead_nonce, 11,
+ aead_cipher,
+ aead_tag, 16);
+}
+
+static void aeadperf_aes128eax(void)
+{
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, aead_key, 16);
+
+ cf_eax_encrypt(&cf_aes, &ctx,
+ aead_msg, bracket,
+ aead_aad, sizeof aead_aad,
+ aead_nonce, 12,
+ aead_cipher,
+ aead_tag, 16);
+}
+
+static void aeadperf_aes256gcm(void)
+{
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, aead_key, 32);
+
+ cf_gcm_encrypt(&cf_aes, &ctx,
+ aead_msg, bracket,
+ aead_aad, sizeof aead_aad,
+ aead_nonce, 12,
+ aead_cipher,
+ aead_tag, 16);
+}
+
+static void aeadperf_aes256ccm(void)
+{
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, aead_key, 32);
+
+ cf_ccm_encrypt(&cf_aes, &ctx,
+ aead_msg, bracket,
+ 4,
+ aead_aad, sizeof aead_aad,
+ aead_nonce, 11,
+ aead_cipher,
+ aead_tag, 16);
+}
+
+static void aeadperf_aes256eax(void)
+{
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, aead_key, 32);
+
+ cf_eax_encrypt(&cf_aes, &ctx,
+ aead_msg, bracket,
+ aead_aad, sizeof aead_aad,
+ aead_nonce, 12,
+ aead_cipher,
+ aead_tag, 16);
+}
+
+/* Provided by linkscript */
+extern uint32_t __HeapLimit;
+
+#define STACK_MAGIC 0x57ac34df
+
+static __attribute__((noinline)) void clear_stack(void)
+{
+ uint32_t *stack_start = &__HeapLimit;
+ uint32_t ss = 0, *stack_stop = &ss;
+ size_t words = stack_stop - stack_start;
+ for (size_t i = 0; i < words; i++)
+ stack_start[i] = STACK_MAGIC;
+}
+
+static __attribute__((noinline)) uint32_t measure_stack(void)
+{
+ uint32_t *stack_start = &__HeapLimit;
+ uint32_t ss, *stack_stop = &ss;
+ size_t words = stack_stop - stack_start;
+ for (size_t i = 0; i < words; i++)
+ if (stack_start[i] != STACK_MAGIC)
+ return words - i + 4; /* we used 4 words for ourselves, roughly */
+
+ return 0;
+}
+
+static void measure(measure_fn fn)
+{
+ clear_stack();
+ uint32_t start_cycles = reset_cycles();
+ fn();
+ uint32_t end_cycles = get_cycles();
+ uint32_t stack_words = measure_stack();
+
+ emit("cycles = ");
+ emit_uint32(end_cycles - start_cycles);
+ emit("\n");
+ emit("stack = ");
+ emit_uint32(stack_words << 2);
+ emit("\n");
+}
+
+#define STRING_(x) #x
+#define STRING(x) STRING_(x)
+
+int main(void)
+{
+ emit(STRING(TEST) "\n");
+#ifdef BRACKET_MODE
+ for (bracket = BRACKET_START; bracket <= BRACKET_END; bracket += BRACKET_STEP)
+ {
+ emit("bracket = ");
+ emit_uint32(bracket);
+ emit("\n");
+ measure(TEST);
+ }
+#else
+ measure(TEST);
+#endif
+ quit_success();
+
+ (void) bracket;
+ (void) do_nothing;
+ (void) stack_8w;
+ (void) stack_64w;
+ (void) hashtest_sha256;
+ (void) hashtest_sha512;
+ (void) hashtest_sha3_256;
+ (void) hashtest_sha3_512;
+ (void) aes128block_test;
+ (void) aes128sched_test;
+ (void) aes256block_test;
+ (void) aes256sched_test;
+ (void) aes128gcm_test;
+ (void) aes128eax_test;
+ (void) aes128ccm_test;
+ (void) salsa20_test;
+ (void) chacha20_test;
+ (void) curve25519_test;
+ (void) poly1305_test;
+ (void) hmacsha256_test;
+ (void) norx_test;
+ (void) aeadperf_norx;
+ (void) aeadperf_chacha20poly1305;
+ (void) aeadperf_aes128gcm;
+ (void) aeadperf_aes128ccm;
+ (void) aeadperf_aes128eax;
+ (void) aeadperf_aes256gcm;
+ (void) aeadperf_aes256ccm;
+ (void) aeadperf_aes256eax;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memcpy.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memcpy.s
new file mode 100644
index 00000000..63406fe5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memcpy.s
@@ -0,0 +1,49 @@
+ .text
+ .syntax unified
+ .global memcpy
+ .func memcpy
+ .thumb_func
+
+memcpy:
+ /* on entry
+ * r0 = targ
+ * r1 = src
+ * r2 = len (bytes)
+ * on exit
+ * r0 = targ (unchanged)
+ */
+ push {r0, r4, lr}
+
+ /* If targ or src are unaligned, drop to byte
+ * processing. */
+ mov r3, r0
+ movs r4, #3
+ orrs r3, r1
+ ands r3, r4
+ bne L_bytewise
+
+ /* Process words */
+L_wordwise:
+ cmp r2, #4
+ blo L_bytewise
+ ldr r4, [r1]
+ adds r1, #4
+ str r4, [r0]
+ adds r0, #4
+ subs r2, #4
+ b L_wordwise
+
+ /* Process bytes */
+L_bytewise:
+ cmp r2, #0
+ beq L_fin
+ ldrb r4, [r1]
+ adds r1, #1
+ strb r4, [r0]
+ adds r0, #1
+ subs r2, #1
+ b L_bytewise
+
+L_fin:
+ pop {r0, r4, pc}
+ .endfunc
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memset.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memset.s
new file mode 100644
index 00000000..a5019667
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/memset.s
@@ -0,0 +1,50 @@
+ .text
+ .syntax unified
+ .global memset
+ .func memset
+ .thumb_func
+
+memset:
+ /* on entry
+ * r0 = targ
+ * r1 = value
+ * r2 = len (bytes)
+ * on exit
+ * r0 = targ (unchanged)
+ */
+ push {r0, r4, lr}
+
+ /* If targ is unaligned, drop to byte
+ * processing. */
+ movs r3, #3
+ ands r3, r0
+ bne L_bytewise
+
+ /* Process words */
+ /* Build r4 by repeating r1. */
+ uxtb r4, r1
+ lsls r3, r4, #8
+ orrs r4, r3
+ lsls r3, r4, #16
+ orrs r4, r3
+
+L_wordwise:
+ cmp r2, #4
+ blo L_bytewise
+ str r4, [r0]
+ adds r0, #4
+ subs r2, #4
+ b L_wordwise
+
+ /* Process bytes */
+L_bytewise:
+ cmp r2, #0
+ beq L_fin
+ strb r1, [r0]
+ adds r0, #1
+ subs r2, #1
+ b L_bytewise
+
+L_fin:
+ pop {r0, r4, pc}
+ .endfunc
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/merge.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/merge.py
new file mode 100644
index 00000000..71d50895
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/merge.py
@@ -0,0 +1,26 @@
+import sys
+
+def extract_results(results):
+ index = 0
+ while index < len(results):
+ if results[index].startswith('## '):
+ end = results.index('\n', index)
+ yield results[index:end]
+ index += 1
+
+def merge(readme, res):
+ title, table = res[0], res[1:]
+ assert title in readme, 'Section ' + title + ' missing from README.md'
+ secindex = readme.index(title)
+ hdrindex = [i for i in range(secindex, len(readme)) if readme[i].startswith('---------- | ')][0]
+ start = hdrindex - 1
+ end = readme.index('\n', start)
+ table = [t.rstrip() + '\n' for t in table]
+ return readme[:start] + table + readme[end:]
+
+results = sys.stdin.readlines()
+readme = open('../../README.md').readlines()
+
+for res in extract_results(results):
+ readme = merge(readme, res)
+print ''.join(readme).rstrip()
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg
new file mode 100644
index 00000000..85af4733
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.efm32.cfg
@@ -0,0 +1,3 @@
+source [find interface/jlink.cfg]
+transport select swd
+source [find target/efm32.cfg]
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg
new file mode 100644
index 00000000..e9356f75
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f0.cfg
@@ -0,0 +1,3 @@
+source [find interface/stlink-v2.cfg]
+transport select hla_swd
+source [find target/stm32f0x.cfg]
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg
new file mode 100644
index 00000000..1108ea07
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f1.cfg
@@ -0,0 +1,3 @@
+source [find interface/stlink-v2.cfg]
+transport select hla_swd
+source [find target/stm32f1x.cfg]
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg
new file mode 100644
index 00000000..de023b84
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/openocd.stm32f3.cfg
@@ -0,0 +1,3 @@
+source [find interface/stlink-v2.cfg]
+transport select hla_swd
+source [find target/stm32f3x.cfg]
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/report.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/report.py
new file mode 100644
index 00000000..718ab24e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/report.py
@@ -0,0 +1,276 @@
+"""
+Interprets logs from test runs. Outputs ASCII
+tables containing results, json data, etc.
+"""
+
+import json
+import sys
+
+archs = 'stm32f0 stm32f1 stm32f3'.split()
+tests = """
+aes128block_test
+aes256block_test
+aes128sched_test
+aes256sched_test
+hashtest_sha256
+hashtest_sha512
+hashtest_sha3_256
+hashtest_sha3_512
+aes128gcm_test
+aes128eax_test
+aes128ccm_test
+norx_test
+salsa20_test
+chacha20_test
+poly1305_test
+hmacsha256_test
+curve25519_test
+aeadperf_norx
+aeadperf_aes128gcm
+aeadperf_aes128eax
+aeadperf_aes128ccm
+aeadperf_aes256gcm
+aeadperf_aes256eax
+aeadperf_aes256ccm
+aeadperf_chacha20poly1305
+do_nothing
+""".split()
+
+arch_names = dict(
+ stm32f0 = 'Cortex-M0',
+ stm32f1 = 'Cortex-M3',
+ stm32f3 = 'Cortex-M4F'
+ )
+
+base_test = 'do_nothing'
+
+def extract(arch, test):
+ fn = 'run.%s.%s.log' % (test, arch)
+
+ code_size = 0
+ data_size = 0
+ cycle_count = None
+ stack_usage = None
+ brackets = None
+ current_bracket = None
+
+ try:
+ lines = open(fn).readlines()
+ except IOError:
+ return None
+
+ for l in lines:
+ if 'LOAD' in l:
+ parts = l.split()
+ assert len(parts) >= 8
+ assert 'LOAD' == parts[0]
+ if parts[6] == 'RWE':
+ code_size += long(parts[5], 16)
+ if parts[6] == 'RW':
+ data_size += long(parts[5], 16)
+
+ if l.startswith('bracket = '):
+ bracket = long(l.split(' = ')[1].strip(), 16)
+ current_bracket = bracket
+ if brackets is None:
+ brackets = {}
+ brackets[current_bracket] = dict()
+
+ if l.startswith('cycles = '):
+ cycle_count = long(l.split(' = ')[1].strip(), 16)
+ if current_bracket is not None:
+ brackets[current_bracket]['cycle_count'] = cycle_count
+
+ if l.startswith('stack = '):
+ stack_usage = long(l.split(' = ')[1].strip(), 16)
+ if current_bracket is not None:
+ brackets[current_bracket]['stack_usage'] = stack_usage
+
+ return dict(
+ code_size = code_size,
+ data_size = data_size,
+ cycle_count = cycle_count,
+ stack_usage = stack_usage,
+ brackets = brackets
+ )
+
+def print_table(rows):
+ header, rows = rows[0], rows[1:]
+ assert not [True for r in rows if len(r) != len(header)]
+ widths = []
+ for i, h in enumerate(header):
+ widths.append(max([len(h)] + [len(r[i]) for r in rows]))
+
+ def print_row(row):
+ print ' | '.join(c + (' ' * (widths[i] - len(c))) for i, c in enumerate(row))
+
+ print_row(header)
+ print_row(['-' * w for w in widths])
+ for r in rows:
+ print_row(r)
+
+results = {}
+
+for arch in archs:
+ for test in tests:
+ inf = extract(arch, test)
+ if inf:
+ results.setdefault(arch, {})[test] = inf
+
+for arch in results.keys():
+ if base_test not in results[arch]:
+ print 'need', base_test, 'results to report for', arch
+ continue
+
+ base_result = results[arch][base_test]
+
+ for test in results[arch].keys():
+ if test == base_test:
+ continue
+
+ results[arch][test]['code_size'] -= base_result['code_size']
+
+def tabulate_aes(arch, block_result, sched_result, table = None):
+ if table is None:
+ table = []
+ table.append((
+ 'Core',
+ 'Cycles (key schedule + block)',
+ 'Cycles (key schedule)',
+ 'Cycles (block)',
+ 'Stack',
+ 'Code size'
+ ))
+
+ table.append(
+ (
+ arch_names[arch],
+ '%d' % block_result['cycle_count'],
+ '%d' % sched_result['cycle_count'],
+ '%d' % (block_result['cycle_count'] - sched_result['cycle_count']),
+ '%dB' % block_result['stack_usage'],
+ '%dB' % block_result['code_size']
+ ))
+
+ return table
+
+def print_std(result):
+ print """* **Cycles**: %(cycle_count)d
+* **Stack**: %(stack_usage)dB
+* **Code size**: %(code_size)dB
+""" % result
+
+def tabulate_std(arch, result, table = None):
+ if table is None:
+ table = []
+ table.append(('Core', 'Cycles', 'Stack', 'Code size'))
+
+ table.append(
+ (
+ arch_names[arch],
+ '%d' % result['cycle_count'],
+ '%dB' % result['stack_usage'],
+ '%dB' % result['code_size']
+ ))
+
+ return table
+
+def tabulate(mktab):
+ table = None
+ for arch in archs:
+ if arch not in results:
+ continue
+ table = mktab(arch, table)
+ print_table(table)
+
+def convert_brackets(metric, tests):
+ for arch in archs:
+ arch_result = {}
+
+ # collect results for each test
+ for t in tests:
+ if arch not in results or t not in results[arch]:
+ print 'missing', arch, t
+ continue
+ data = results[arch][t]['brackets']
+ arch_result[t] = [[b, data[b][metric]] for b in sorted(data.keys())]
+
+ # convert into list of [bracket, test-1, test-2, ...] lists
+ out = []
+ if len(arch_result) == 0:
+ continue
+ first_row = arch_result.values()[0]
+
+ for i in range(len(first_row)):
+ row = [ first_row[i][0] ]
+
+ for k in sorted(arch_result.keys()):
+ if len(arch_result[k]) != len(first_row):
+ print 'warn:', 'test', k, 'did not complete?'
+ rr = arch_result[k][i]
+ row.append(rr[1])
+
+ out.append(row)
+
+ print json.dumps(out)
+
+convert_brackets('cycle_count',
+ [
+ 'aeadperf_norx',
+ 'aeadperf_aes128gcm',
+ 'aeadperf_aes128eax',
+ 'aeadperf_aes128ccm',
+ 'aeadperf_aes256gcm',
+ 'aeadperf_aes256eax',
+ 'aeadperf_aes256ccm',
+ 'aeadperf_chacha20poly1305'
+ ])
+convert_brackets('stack_usage',
+ [
+ 'aeadperf_norx',
+ 'aeadperf_aes128gcm',
+ 'aeadperf_aes128eax',
+ 'aeadperf_aes128ccm',
+ 'aeadperf_aes256gcm',
+ 'aeadperf_aes256eax',
+ 'aeadperf_aes256ccm',
+ 'aeadperf_chacha20poly1305'
+ ])
+
+# screwed if we need other block ciphers
+print '###', '128-bit key'
+tabulate(lambda arch, table: tabulate_aes(arch, results[arch]['aes128block_test'], results[arch]['aes128sched_test'], table))
+print
+
+print '###', '256-bit key'
+tabulate(lambda arch, table: tabulate_aes(arch, results[arch]['aes256block_test'], results[arch]['aes256sched_test'], table))
+print
+
+def do_table(title, test):
+ print '##', title
+ tabulate(lambda arch, table: tabulate_std(arch, results[arch][test], table))
+ print
+
+do_table('AES128-GCM', 'aes128gcm_test')
+do_table('AES128-EAX', 'aes128eax_test')
+do_table('AES128-CCM', 'aes128ccm_test')
+do_table('NORX32', 'norx_test')
+do_table('ChaCha20', 'chacha20_test')
+do_table('Salsa20', 'salsa20_test')
+do_table('SHA256', 'hashtest_sha256')
+do_table('SHA512', 'hashtest_sha512')
+do_table('SHA3-256', 'hashtest_sha3_256')
+do_table('SHA3-512', 'hashtest_sha3_512')
+do_table('HMAC-SHA256', 'hmacsha256_test')
+do_table('Poly1305-AES', 'poly1305_test')
+do_table('Curve25519', 'curve25519_test')
+
+if '--aead' in sys.argv:
+ do_table('AEAD-Shootout: NORX', 'aeadperf_norx')
+ do_table('AEAD-Shootout: AES-128-GCM', 'aeadperf_aes128gcm')
+ do_table('AEAD-Shootout: AES-128-EAX', 'aeadperf_aes128eax')
+ do_table('AEAD-Shootout: AES-128-CCM', 'aeadperf_aes128ccm')
+ do_table('AEAD-Shootout: AES-256-GCM', 'aeadperf_aes256gcm')
+ do_table('AEAD-Shootout: AES-256-EAX', 'aeadperf_aes256eax')
+ do_table('AEAD-Shootout: AES-256-CCM', 'aeadperf_aes256ccm')
+ do_table('AEAD-Shootout: ChaCha20-Poly1305', 'aeadperf_chacha20poly1305')
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.c
new file mode 100644
index 00000000..cbe5aa2e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.c
@@ -0,0 +1,170 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "semihost.h"
+
+#define OP_WRITE0 0x04
+#define OP_EXIT 0x18
+#define OP_EXIT_ARG_FAILURE 0x0
+#define OP_EXIT_ARG_SUCCESS 0x20026
+
+extern uint32_t semihost(uint32_t, volatile void *);
+
+__attribute__((noreturn))
+void quit_success(void)
+{
+ semihost(OP_EXIT, (void *) OP_EXIT_ARG_SUCCESS);
+ while (1)
+ ;
+}
+
+__attribute__((noreturn))
+void quit_failure(void)
+{
+ semihost(OP_EXIT, (void *) OP_EXIT_ARG_FAILURE);
+ while (1)
+ ;
+}
+
+void emit(const char *buf)
+{
+ semihost(OP_WRITE0, (volatile void *) buf);
+}
+
+static void emit_extent(const char *start, const char *end)
+{
+ char buf[32+1];
+ size_t bufmax = sizeof(buf) - 1;
+ buf[32] = 0;
+
+ size_t bytes = end - start + 1;
+
+ while (bytes >= bufmax)
+ {
+ memcpy(buf, start, bufmax);
+ emit(buf);
+ bytes -= bufmax;
+ start += bufmax;
+ }
+
+ if (bytes == 0)
+ return;
+
+ memcpy(buf, start, bytes);
+ buf[bytes] = 0;
+ emit(buf);
+}
+
+void emitf(const char *fmt, ...)
+{
+ const char *start = fmt, *end = fmt;
+
+ va_list args;
+ va_start(args, fmt);
+
+ while (*fmt)
+ {
+ switch (*fmt)
+ {
+ case '%':
+ emit_extent(start, end);
+
+ switch (fmt[1])
+ {
+ case '%':
+ emit("%");
+ break;
+
+ case 'u':
+ emit_uint32(va_arg(args, uint32_t));
+ break;
+
+ case 's':
+ emit(va_arg(args, const char *));
+ break;
+ }
+ start = end = fmt + 2;
+ break;
+
+ default:
+ end = fmt;
+ break;
+ }
+
+ fmt++;
+ }
+
+ va_end(args);
+ emit_extent(start, end);
+}
+
+static const char *hex_chars = "0123456789abcdef";
+
+void emit_hex(const void *ptr, size_t len)
+{
+ const uint8_t *bb = ptr;
+ char byte[3];
+
+ byte[2] = 0;
+
+ for (size_t i = 0; i < len; i++)
+ {
+ byte[0] = hex_chars[(bb[i] >> 4) & 0xf];
+ byte[1] = hex_chars[bb[i] & 0xf];
+ emit(byte);
+ }
+}
+
+void emit_uint32(uint32_t x)
+{
+ char buf[sizeof "0x11223344"];
+ buf[0] = '0';
+ buf[1] = 'x';
+ buf[2] = hex_chars[(x >> 28) & 0xf];
+ buf[3] = hex_chars[(x >> 24) & 0xf];
+ buf[4] = hex_chars[(x >> 20) & 0xf];
+ buf[5] = hex_chars[(x >> 16) & 0xf];
+ buf[6] = hex_chars[(x >> 12) & 0xf];
+ buf[7] = hex_chars[(x >> 8) & 0xf];
+ buf[8] = hex_chars[(x >> 4) & 0xf];
+ buf[9] = hex_chars[x & 0xf];
+ buf[10] = 0;
+
+ emit(buf);
+}
+
+typedef struct
+{
+ volatile uint32_t ctrl;
+ volatile uint32_t reload;
+ volatile uint32_t current;
+} systick;
+
+#define SysTick ((systick *)0xe000e010)
+
+#define STCTRL_SYSCLOCK 0x04
+#define STCTRL_TICKINT 0x02
+#define STCTRL_ENABLE 0x01
+
+#define STCTRL_MAX 0xffffff
+#define STCTRL_SHIFT 24
+
+extern uint32_t get_ticks(void);
+extern void reset_ticks(void);
+
+uint32_t reset_cycles(void)
+{
+ SysTick->reload = STCTRL_MAX;
+ SysTick->ctrl = STCTRL_SYSCLOCK | STCTRL_TICKINT | STCTRL_ENABLE;
+ SysTick->current = 0;
+ reset_ticks();
+ return get_ticks();
+}
+
+uint32_t get_cycles(void)
+{
+ return (get_ticks() << STCTRL_SHIFT) + (STCTRL_MAX - SysTick->current);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.h
new file mode 100644
index 00000000..cf6f01a5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.h
@@ -0,0 +1,40 @@
+#ifndef SEMIHOST_H
+#define SEMIHOST_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/* Exits emulator with success (or merely hangs). */
+__attribute__((noreturn))
+void quit_success(void);
+
+/* Exits emulator with failure (or merely hangs). */
+__attribute__((noreturn))
+void quit_failure(void);
+
+/* Writes zero terminated string to debug output */
+void emit(const char *buf);
+
+/* Writes a formatting string to debug output.
+ *
+ * Supported:
+ * %u - uint32_t argument, same as emit_uint32
+ * %s - const char * argument, same as emit
+ */
+void emitf(const char *fmt, ...);
+
+/* Writes hex dump of len bytes at ptr to debug output. */
+void emit_hex(const void *ptr, size_t len);
+
+/* Writes value v in hex to debug output, in format:
+ * 0xHHHHHHHH (equivalent to printf 0x%08x). */
+void emit_uint32(uint32_t v);
+
+/* Reset cycle counter to 0. Returns the current value
+ * (just after resetting it). */
+uint32_t reset_cycles(void);
+
+/* Return the value of the cycle counter. */
+uint32_t get_cycles(void);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.s
new file mode 100644
index 00000000..0fddf045
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/semihost.s
@@ -0,0 +1,15 @@
+ .text
+ .syntax unified
+ .global semihost
+ .func semihost
+ .thumb_func
+
+semihost:
+ /* on entry
+ * r0 = op
+ * r1 = arg */
+ push {r7, lr}
+ bkpt 0xab
+ pop {r7, pc}
+
+ .endfunc
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s
new file mode 100644
index 00000000..49e3b5d0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_mpy121666.s
@@ -0,0 +1,199 @@
+// Implementation of multiplication of an fe25519 bit value with the curve constant 121666.
+//
+// B. Haase, Endress + Hauser Conducta GmbH & Ko. KG
+// public domain.
+//
+// gnu assembler format.
+//
+// Generated and tested with C++ functions in the test subdirectory.
+//
+// ATTENTION:
+// Not yet tested on target hardware.
+
+
+ .cpu cortex-m0
+ .fpu softvfp
+ .eabi_attribute 20, 1
+ .eabi_attribute 21, 1
+ .eabi_attribute 23, 3
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+ .eabi_attribute 26, 1
+ .eabi_attribute 30, 2
+ .eabi_attribute 34, 0
+ .eabi_attribute 18, 4
+ .code 16
+
+ .file "cortex_m0_reduce25519.s"
+
+ .text
+ .align 2
+
+ .global fe25519_mpyWith121666_asm
+ .code 16
+ .thumb_func
+ .type fe25519_mpyWith121666_asm, %function
+
+fe25519_mpyWith121666_asm:
+ push {r4,r5,r6,r7,r14}
+ ldr r7,__label_for_immediate_56130
+ ldr r2,[r1,#28]
+ lsl r5,r2,#16
+ lsr r6,r2,#16
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r5,r2
+ mov r2,#0
+ adc r6,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r5,r2
+ adc r6,r3
+ lsl r2,r5,#1
+ lsr r2,r2,#1
+ str r2,[r0,#28]
+ lsr r5,r5,#31
+ lsl r6,r6,#1
+ orr r5,r6
+ mov r6,#19
+ mul r5,r6
+ mov r6,#0
+ ldr r2,[r1,#0]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r5,r3
+ adc r6,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r5,r2
+ mov r2,#0
+ adc r6,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r5,r2
+ adc r6,r3
+ str r5,[r0,#0]
+ mov r5,#0
+ ldr r2,[r1,#4]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r6,r3
+ adc r5,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r6,r2
+ mov r2,#0
+ adc r5,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r6,r2
+ adc r5,r3
+ str r6,[r0,#4]
+ mov r6,#0
+ ldr r2,[r1,#8]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r5,r3
+ adc r6,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r5,r2
+ mov r2,#0
+ adc r6,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r5,r2
+ adc r6,r3
+ str r5,[r0,#8]
+ mov r5,#0
+ ldr r2,[r1,#12]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r6,r3
+ adc r5,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r6,r2
+ mov r2,#0
+ adc r5,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r6,r2
+ adc r5,r3
+ str r6,[r0,#12]
+ mov r6,#0
+ ldr r2,[r1,#16]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r5,r3
+ adc r6,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r5,r2
+ mov r2,#0
+ adc r6,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r5,r2
+ adc r6,r3
+ str r5,[r0,#16]
+ mov r5,#0
+ ldr r2,[r1,#20]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r6,r3
+ adc r5,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r6,r2
+ mov r2,#0
+ adc r5,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r6,r2
+ adc r5,r3
+ str r6,[r0,#20]
+ mov r6,#0
+ ldr r2,[r1,#24]
+ lsl r3,r2,#16
+ lsr r4,r2,#16
+ add r5,r3
+ adc r6,r4
+ lsr r3,r2,#16
+ uxth r2,r2
+ mul r2,r7
+ mul r3,r7
+ add r5,r2
+ mov r2,#0
+ adc r6,r2
+ lsl r2,r3,#16
+ lsr r3,r3,#16
+ add r5,r2
+ adc r6,r3
+ str r5,[r0,#24]
+ mov r5,#0
+ ldr r2,[r0,#28]
+ add r6,r2
+ str r6,[r0,#28]
+ pop {r4,r5,r6,r7,r15}
+
+ .align 2
+__label_for_immediate_56130:
+ .word 56130
+
+ .size fe25519_mpyWith121666_asm, .-fe25519_mpyWith121666_asm
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s
new file mode 100644
index 00000000..4c09f5ea
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/cortex_m0_reduce25519.s
@@ -0,0 +1,176 @@
+// Implementation of a partial reduction modulo 2^255 - 38.
+//
+// B. Haase, Endress + Hauser Conducta GmbH & Ko. KG
+// public domain.
+//
+// gnu assembler format.
+//
+// Generated and tested with C++ functions in the test subdirectory and on the target.
+//
+
+ .cpu cortex-m0
+ .fpu softvfp
+ .eabi_attribute 20, 1
+ .eabi_attribute 21, 1
+ .eabi_attribute 23, 3
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+ .eabi_attribute 26, 1
+ .eabi_attribute 30, 2
+ .eabi_attribute 34, 0
+ .eabi_attribute 18, 4
+ .code 16
+
+ .file "cortex_m0_reduce25519.s"
+
+ .text
+ .align 2
+
+ .global fe25519_reduceTo256Bits_asm
+ .code 16
+ .thumb_func
+ .type fe25519_reduceTo256Bits_asm, %function
+
+fe25519_reduceTo256Bits_asm:
+ push {r4,r5,r6,r7,r14}
+ ldr r2,[r1,#60]
+ lsr r3,r2,#16
+ uxth r2,r2
+ mov r7,#38
+ mul r2,r7
+ mul r3,r7
+ ldr r4,[r1,#28]
+ lsr r5,r3,#16
+ lsl r3,r3,#16
+ mov r6,#0
+ add r4,r2
+ adc r5,r6
+ add r4,r3
+ adc r5,r6
+ lsl r2,r4,#1
+ lsr r2,r2,#1
+ str r2,[r0,#28]
+ lsr r4,r4,#31
+ lsl r5,r5,#1
+ orr r4,r5
+ mov r2,#19
+ mul r2,r4
+ ldr r4,[r1,#0]
+ add r2,r4
+ mov r3,#0
+ adc r3,r6
+ ldr r4,[r1,#32]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r2,r4
+ adc r3,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ str r2,[r0,#0]
+ ldr r4,[r1,#4]
+ add r3,r4
+ mov r2,#0
+ adc r2,r6
+ ldr r4,[r1,#36]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r3,r4
+ adc r2,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r3,r4
+ adc r2,r5
+ str r3,[r0,#4]
+ ldr r4,[r1,#8]
+ add r2,r4
+ mov r3,#0
+ adc r3,r6
+ ldr r4,[r1,#40]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r2,r4
+ adc r3,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ str r2,[r0,#8]
+ ldr r4,[r1,#12]
+ add r3,r4
+ mov r2,#0
+ adc r2,r6
+ ldr r4,[r1,#44]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r3,r4
+ adc r2,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r3,r4
+ adc r2,r5
+ str r3,[r0,#12]
+ ldr r4,[r1,#16]
+ add r2,r4
+ mov r3,#0
+ adc r3,r6
+ ldr r4,[r1,#48]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r2,r4
+ adc r3,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ str r2,[r0,#16]
+ ldr r4,[r1,#20]
+ add r3,r4
+ mov r2,#0
+ adc r2,r6
+ ldr r4,[r1,#52]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r3,r4
+ adc r2,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r3,r4
+ adc r2,r5
+ str r3,[r0,#20]
+ ldr r4,[r1,#24]
+ add r2,r4
+ mov r3,#0
+ adc r3,r6
+ ldr r4,[r1,#56]
+ lsr r5,r4,#16
+ uxth r4,r4
+ mul r5,r7
+ mul r4,r7
+ add r2,r4
+ adc r3,r6
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ str r2,[r0,#24]
+ ldr r4,[r0,#28]
+ add r4,r3
+ str r4,[r0,#28]
+ pop {r4,r5,r6,r7,r15}
+
+ .size fe25519_reduceTo256Bits_asm, .-fe25519_reduceTo256Bits_asm
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s
new file mode 100644
index 00000000..155674c6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/mul.s
@@ -0,0 +1,1109 @@
+ .align 2
+ .global multiply256x256_asm
+ .type multiply256x256_asm, %function
+multiply256x256_asm:
+ push {r4-r7,lr}
+ mov r3, r8
+ mov r4, r9
+ mov r5, r10
+ mov r6, r11
+ push {r0-r6}
+ mov r12, r0
+ mov r10, r2
+ mov r11, r1
+ mov r0,r2
+ ldm r0!, {r4,r5,r6,r7}
+ ldm r1!, {r2,r3,r6,r7}
+ push {r0,r1}
+ /////////BEGIN LOW PART //////////////////////
+ /////////MUL128/////////////
+ //MUL64
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ //////////////////////////
+ mov r4, r12
+ stm r4!, {r0,r1}
+ push {r4}
+ push {r0,r1}
+ mov r1, r10
+ mov r10, r2
+ ldm r1, {r0, r1, r4, r5}
+ mov r2, r4
+ mov r7, r5
+ sub r2, r0
+ sbc r7, r1
+ sbc r6, r6
+ eor r2, r6
+ eor r7, r6
+ sub r2, r6
+ sbc r7, r6
+ push {r2, r7}
+ mov r2, r11
+ mov r11, r3
+ ldm r2, {r0, r1, r2, r3}
+ sub r0, r2
+ sbc r1, r3
+ sbc r7, r7
+ eor r0, r7
+ eor r1, r7
+ sub r0, r7
+ sbc r1, r7
+ eor r7, r6
+ mov r12, r7
+ push {r0, r1}
+ //MUL64
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ mov r4, r10
+ mov r5, r11
+ eor r6, r6
+ add r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r6
+ mov r10, r2
+ mov r11, r3
+ pop {r2-r5}
+ push {r0, r1}
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ pop {r4, r5}
+ mov r6, r12
+ mov r7, r12
+ eor r0, r6
+ eor r1, r6
+ eor r2, r6
+ eor r3, r6
+ asr r6, r6, #1
+ adc r0, r4
+ adc r1, r5
+ adc r4, r2
+ adc r5, r3
+ eor r2, r2
+ adc r6,r2
+ adc r7,r2
+ pop {r2, r3}
+ mov r8, r2
+ mov r9, r3
+ add r2, r0
+ adc r3, r1
+ mov r0, r10
+ mov r1, r11
+ adc r4, r0
+ adc r5, r1
+ adc r6, r0
+ adc r7, r1
+ ////////END LOW PART/////////////////////
+ pop {r0}
+ stm r0!, {r2,r3}
+ pop {r1,r2}
+ push {r0}
+ push {r4-r7}
+ mov r10, r1
+ mov r11, r2
+ ldm r1!, {r4, r5}
+ ldm r2, {r2, r3}
+ /////////BEGIN HIGH PART////////////////
+ /////////MUL128/////////////
+ //MUL64
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ push {r0,r1}
+ mov r1, r10
+ mov r10, r2
+ ldm r1, {r0, r1, r4, r5}
+ mov r2, r4
+ mov r7, r5
+ sub r2, r0
+ sbc r7, r1
+ sbc r6, r6
+ eor r2, r6
+ eor r7, r6
+ sub r2, r6
+ sbc r7, r6
+ push {r2, r7}
+ mov r2, r11
+ mov r11, r3
+ ldm r2, {r0, r1, r2, r3}
+ sub r0, r2
+ sbc r1, r3
+ sbc r7, r7
+ eor r0, r7
+ eor r1, r7
+ sub r0, r7
+ sbc r1, r7
+ eor r7, r6
+ mov r12, r7
+ push {r0, r1}
+ //MUL64
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ mov r4, r10
+ mov r5, r11
+ eor r6, r6
+ add r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r6
+ mov r10, r2
+ mov r11, r3
+ pop {r2-r5}
+ push {r0, r1}
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ pop {r4, r5}
+ mov r6, r12
+ mov r7, r12
+ eor r0, r6
+ eor r1, r6
+ eor r2, r6
+ eor r3, r6
+ asr r6, r6, #1
+ adc r0, r4
+ adc r1, r5
+ adc r4, r2
+ adc r5, r3
+ eor r2, r2
+ adc r6,r2 //0,1
+ adc r7,r2
+ pop {r2, r3}
+ mov r8, r2
+ mov r9, r3
+ add r2, r0
+ adc r3, r1
+ mov r0, r10
+ mov r1, r11
+ adc r4, r0
+ adc r5, r1
+ adc r6, r0
+ adc r7, r1
+ ////////END HIGH PART/////////////////////
+ mov r0, r8
+ mov r1, r9
+ mov r8, r6
+ mov r9, r7
+ pop {r6, r7}
+ add r0, r6
+ adc r1, r7
+ pop {r6, r7}
+ adc r2, r6
+ adc r3, r7
+ pop {r7}
+ stm r7!, {r0-r3}
+ mov r10, r7
+ eor r0,r0
+ mov r6, r8
+ mov r7, r9
+ adc r4, r0
+ adc r5, r0
+ adc r6, r0
+ adc r7, r0
+ pop {r0,r1,r2}
+ mov r12, r2
+ push {r0, r4-r7}
+ ldm r1, {r0-r7}
+ sub r0, r4
+ sbc r1, r5
+ sbc r2, r6
+ sbc r3, r7
+ eor r4, r4
+ sbc r4, r4
+ eor r0, r4
+ eor r1, r4
+ eor r2, r4
+ eor r3, r4
+ sub r0, r4
+ sbc r1, r4
+ sbc r2, r4
+ sbc r3, r4
+ mov r6, r12
+ mov r12, r4 //carry
+ mov r5, r10
+ stm r5!, {r0-r3}
+ mov r11, r5
+ mov r8, r0
+ mov r9, r1
+ ldm r6, {r0-r7}
+ sub r4, r0
+ sbc r5, r1
+ sbc r6, r2
+ sbc r7, r3
+ eor r0, r0
+ sbc r0, r0
+ eor r4, r0
+ eor r5, r0
+ eor r6, r0
+ eor r7, r0
+ sub r4, r0
+ sbc r5, r0
+ sbc r6, r0
+ sbc r7, r0
+ mov r1, r12
+ eor r0, r1
+ mov r1, r11
+ stm r1!, {r4-r7}
+ push {r0}
+ mov r2, r8
+ mov r3, r9
+ /////////BEGIN MIDDLE PART////////////////
+ /////////MUL128/////////////
+ //MUL64
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ push {r0,r1}
+ mov r1, r10
+ mov r10, r2
+ ldm r1, {r0, r1, r4, r5}
+ mov r2, r4
+ mov r7, r5
+ sub r2, r0
+ sbc r7, r1
+ sbc r6, r6
+ eor r2, r6
+ eor r7, r6
+ sub r2, r6
+ sbc r7, r6
+ push {r2, r7}
+ mov r2, r11
+ mov r11, r3
+ ldm r2, {r0, r1, r2, r3}
+ sub r0, r2
+ sbc r1, r3
+ sbc r7, r7
+ eor r0, r7
+ eor r1, r7
+ sub r0, r7
+ sbc r1, r7
+ eor r7, r6
+ mov r12, r7
+ push {r0, r1}
+ //MUL64
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ mov r4, r10
+ mov r5, r11
+ eor r6, r6
+ add r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r6
+ mov r10, r2
+ mov r11, r3
+ pop {r2-r5}
+ push {r0, r1}
+ mov r6, r5
+ mov r1, r2
+ sub r5, r4
+ sbc r0, r0
+ eor r5, r0
+ sub r5, r0
+ sub r1, r3
+ sbc r7, r7
+ eor r1, r7
+ sub r1, r7
+ eor r7, r0
+ mov r9, r1
+ mov r8, r5
+ lsr r1,r4,#16
+ uxth r4,r4
+ mov r0,r4
+ uxth r5,r2
+ lsr r2,#16
+ mul r0,r5//00
+ mul r5,r1//10
+ mul r4,r2//01
+ mul r1,r2//11
+ lsl r2,r4,#16
+ lsr r4,r4,#16
+ add r0,r2
+ adc r1,r4
+ lsl r2,r5,#16
+ lsr r4,r5,#16
+ add r0,r2
+ adc r1,r4
+ lsr r4, r6,#16
+ uxth r6, r6
+ uxth r5, r3
+ lsr r3, r3, #16
+ mov r2, r6
+ mul r2, r5
+ mul r5, r4
+ mul r6, r3
+ mul r3, r4
+ lsl r4,r5,#16
+ lsr r5,r5,#16
+ add r2,r4
+ adc r3,r5
+ lsl r4,r6,#16
+ lsr r5,r6,#16
+ add r2,r4
+ adc r3,r5
+ eor r6, r6
+ add r2, r1
+ adc r3, r6
+ mov r1, r9
+ mov r5, r8
+ mov r8, r0
+ lsr r0, r1,#16
+ uxth r1,r1
+ mov r4,r1
+ lsr r6,r5,#16
+ uxth r5,r5
+ mul r1,r5
+ mul r4,r6
+ mul r5,r0
+ mul r0,r6
+ lsl r6,r4,#16
+ lsr r4,#16
+ add r1,r6
+ adc r0,r4
+ lsl r6,r5,#16
+ lsr r5,#16
+ add r1,r6
+ adc r0,r5
+ eor r1,r7
+ eor r0,r7
+ eor r4, r4
+ asr r7, r7, #1
+ adc r1, r2
+ adc r2, r0
+ adc r7, r4
+ mov r0, r8
+ add r1, r0
+ adc r2, r3
+ adc r3, r7
+ pop {r4, r5}
+ mov r6, r12
+ mov r7, r12
+ eor r0, r6
+ eor r1, r6
+ eor r2, r6
+ eor r3, r6
+ asr r6, r6, #1
+ adc r0, r4
+ adc r1, r5
+ adc r4, r2
+ adc r5, r3
+ eor r2, r2
+ adc r6,r2 //0,1
+ adc r7,r2
+ pop {r2, r3}
+ mov r8, r2
+ mov r9, r3
+ add r2, r0
+ adc r3, r1
+ mov r0, r10
+ mov r1, r11
+ adc r4, r0
+ adc r5, r1
+ adc r6, r0
+ adc r7, r1
+ //////////END MIDDLE PART////////////////
+ pop {r0,r1} //r0,r1
+ mov r12, r0 //negative
+ eor r2, r0
+ eor r3, r0
+ eor r4, r0
+ eor r5, r0
+ eor r6, r0
+ eor r7, r0
+ push {r4-r7}
+ ldm r1!, {r4-r7}
+ mov r11, r1 //reference
+ mov r1, r9
+ eor r1, r0
+ mov r10, r4
+ mov r4, r8
+ asr r0, #1
+ eor r0, r4
+ mov r4, r10
+ adc r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r7
+ eor r4, r4
+ adc r4, r4
+ mov r10, r4 //carry
+ mov r4, r11
+ ldm r4, {r4-r7}
+ add r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r7
+ mov r9, r4
+ mov r4, r11
+ stm r4!, {r0-r3}
+ mov r11, r4
+ pop {r0-r3}
+ mov r4, r9
+ adc r4, r0
+ adc r5, r1
+ adc r6, r2
+ adc r7, r3
+ mov r1, #0
+ adc r1, r1
+ mov r0, r10
+ mov r10, r1 //carry
+ asr r0, #1
+ pop {r0-r3}
+ adc r4, r0
+ adc r5, r1
+ adc r6, r2
+ adc r7, r3
+ mov r8, r0
+ mov r0, r11
+ stm r0!, {r4-r7}
+ mov r11, r0
+ mov r0, r8
+ mov r6, r12
+ mov r5, r10
+ eor r4, r4
+ adc r5, r6
+ adc r6, r4
+ add r0, r5
+ adc r1, r6
+ adc r2, r6
+ adc r3, r6
+ mov r7, r11
+ stm r7!, {r0-r3}
+ pop {r3-r6}
+ mov r8, r3
+ mov r9, r4
+ mov r10, r5
+ mov r11, r6
+ pop {r4-r7,pc}
+ bx lr
+.size multiply256x256_asm, .-multiply256x256_asm
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c
new file mode 100644
index 00000000..488aac78
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/scalarmult.c
@@ -0,0 +1,761 @@
+/* =======================
+ ============================ C/C++ HEADER FILE =============================
+ =======================
+
+ Collection of all required submodules from naclM0 required for curve25519
+ scalar multiplication (not including randomization, etc.) alone.
+
+ Library naclM0 largely bases on work avrNacl of M. Hutter and P. Schwabe.
+
+ Will compile to the two functions
+
+ int
+ crypto_scalarmult_base_curve25519(
+ unsigned char* q,
+ const unsigned char* n
+ );
+
+ int
+ crypto_scalarmult_curve25519 (
+ unsigned char* r,
+ const unsigned char* s,
+ const unsigned char* p
+ );
+
+ Requires inttypes.h header and the four external assembly functions
+
+ extern void
+ fe25519_reduceTo256Bits_asm (
+ fe25519 *res,
+ const UN_512bitValue *in
+ );
+
+ extern void
+ fe25519_mpyWith121666_asm (
+ fe25519* out,
+ const fe25519* in
+ );
+
+ extern void
+ multiply256x256_asm (
+ UN_512bitValue* result,
+ const UN_256bitValue* x,
+ const UN_256bitValue* y
+ );
+
+ extern void
+ square256_asm (
+ UN_512bitValue* result,
+ const UN_256bitValue* x
+ );
+
+ \file scalarmult.c
+
+ \Author B. Haase, Endress + Hauser Conducta GmbH & Co. KG
+
+ License: CC Common Creative license Attribution 4.0 International (CC BY 4.0)
+ http://creativecommons.org/licenses/by/4.0/
+ ============================================================================*/
+
+#include <inttypes.h>
+
+// comment out this line if implementing conditional swaps by data moves
+//#define DH_SWAP_BY_POINTERS
+
+// Define the symbol to 0 in order to only use ladder steps
+//#define DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS 1
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+typedef uintptr_t uintptr;
+
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+typedef intptr_t intptr;
+
+// Note that it's important to define the unit8 as first union member, so that
+// an array of uint8 may be used as initializer.
+typedef union UN_256bitValue_
+{
+ uint8 as_uint8[32];
+ uint16 as_uint16[16];
+ uint32 as_uint32[8];
+ uint64 as_uint64[4];
+} UN_256bitValue;
+
+// Note that it's important to define the unit8 as first union member, so that
+// an array of uint8 may be used as initializer.
+typedef union UN_512bitValue_
+{
+ uint8 as_uint8[64];
+ uint16 as_uint16[32];
+ uint32 as_uint32[16];
+ uint64 as_uint64[8];
+ UN_256bitValue as_256_bitValue[2];
+} UN_512bitValue;
+
+typedef UN_256bitValue fe25519;
+
+// ****************************************************
+// Assembly functions.
+// ****************************************************
+
+extern void
+fe25519_reduceTo256Bits_asm(
+ fe25519 *res,
+ const UN_512bitValue *in
+);
+
+#define fe25519_mpyWith121666 fe25519_mpyWith121666_asm
+extern void
+fe25519_mpyWith121666_asm (
+ fe25519* out,
+ const fe25519* in
+);
+
+#define multiply256x256 multiply256x256_asm
+extern void
+multiply256x256(
+ UN_512bitValue* result,
+ const UN_256bitValue* x,
+ const UN_256bitValue* y
+);
+
+#define square256 square256_asm
+extern void
+square256(
+ UN_512bitValue* result,
+ const UN_256bitValue* x
+);
+
+// ****************************************************
+// C functions for fe25519
+// ****************************************************
+
+static void
+fe25519_cpy(
+ fe25519* dest,
+ const fe25519* source
+)
+{
+ uint32 ctr;
+
+ for (ctr = 0; ctr < 8; ctr++)
+ {
+ dest->as_uint32[ctr] = source->as_uint32[ctr];
+ }
+}
+
+static void
+fe25519_unpack(
+ volatile fe25519* out,
+ const unsigned char in[32]
+)
+{
+ uint8 ctr;
+
+ for (ctr = 0; ctr < 32; ctr++)
+ {
+ out->as_uint8[ctr] = in[ctr];
+ }
+ out->as_uint8[31] &= 0x7f; // make sure that the last bit is cleared.
+}
+
+static void
+fe25519_sub(
+ fe25519* out,
+ const fe25519* baseValue,
+ const fe25519* valueToSubstract
+)
+{
+ uint16 ctr;
+ int64 accu = 0;
+
+ // First subtract the most significant word, so that we may
+ // reduce the result "on the fly".
+ accu = baseValue->as_uint32[7];
+ accu -= valueToSubstract->as_uint32[7];
+
+ // We always set bit #31, and compensate this by subtracting 1 from the reduction
+ // value.
+ out->as_uint32[7] = ((uint32)accu) | 0x80000000ul;
+
+ accu = 19 * ((int32)(accu >> 31) - 1);
+ // ^ "-1" is the compensation for the "| 0x80000000ul" above.
+ // This choice makes sure, that the result will be positive!
+
+ for (ctr = 0; ctr < 7; ctr += 1)
+ {
+ accu += baseValue->as_uint32[ctr];
+ accu -= valueToSubstract->as_uint32[ctr];
+
+ out->as_uint32[ctr] = (uint32)accu;
+ accu >>= 32;
+ }
+ accu += out->as_uint32[7];
+ out->as_uint32[7] = (uint32)accu;
+}
+
+static void
+fe25519_add(
+ fe25519* out,
+ const fe25519* baseValue,
+ const fe25519* valueToAdd
+)
+{
+ uint16 ctr = 0;
+ uint64 accu = 0;
+
+ // We first add the most significant word, so that we may reduce
+ // "on the fly".
+ accu = baseValue->as_uint32[7];
+ accu += valueToAdd->as_uint32[7];
+ out->as_uint32[7] = ((uint32)accu) & 0x7ffffffful;
+
+ accu = ((uint32)(accu >> 31)) * 19;
+
+ for (ctr = 0; ctr < 7; ctr += 1)
+ {
+ accu += baseValue->as_uint32[ctr];
+ accu += valueToAdd->as_uint32[ctr];
+
+ out->as_uint32[ctr] = (uint32)accu;
+ accu >>= 32;
+ }
+ accu += out->as_uint32[7];
+ out->as_uint32[7] = (uint32)accu;
+}
+
+static void
+fe25519_mul(
+ fe25519* result,
+ const fe25519* in1,
+ const fe25519* in2
+)
+{
+ UN_512bitValue tmp;
+
+ multiply256x256(&tmp, in1, in2);
+ fe25519_reduceTo256Bits_asm(result,&tmp);
+}
+
+static void
+fe25519_square(
+ fe25519* result,
+ const fe25519* in
+)
+{
+ UN_512bitValue tmp;
+
+ square256(&tmp, in);
+ fe25519_reduceTo256Bits_asm(result,&tmp);
+}
+
+static void
+fe25519_reduceCompletely(
+ volatile fe25519* inout
+)
+{
+ uint32 numberOfTimesToSubstractPrime;
+ uint32 initialGuessForNumberOfTimesToSubstractPrime = inout->as_uint32[7] >>
+ 31;
+ uint64 accu;
+ uint8 ctr;
+
+ // add one additional 19 to the estimated number of reductions.
+ // Do the calculation without writing back the results to memory.
+ //
+ // The initial guess of required numbers of reductions is based
+ // on bit #32 of the most significant word.
+ // This initial guess may be wrong, since we might have a value
+ // v in the range
+ // 2^255 - 19 <= v < 2^255
+ // . After adding 19 to the value, we will be having the correct
+ // Number of required subtractions.
+ accu = initialGuessForNumberOfTimesToSubstractPrime * 19 + 19;
+
+ for (ctr = 0; ctr < 7; ctr++)
+ {
+ accu += inout->as_uint32[ctr];
+ accu >>= 32;
+ }
+ accu += inout->as_uint32[7];
+
+ numberOfTimesToSubstractPrime = (uint32)(accu >> 31);
+
+ // Do the reduction.
+ accu = numberOfTimesToSubstractPrime * 19;
+
+ for (ctr = 0; ctr < 7; ctr++)
+ {
+ accu += inout->as_uint32[ctr];
+ inout->as_uint32[ctr] = (uint32)accu;
+ accu >>= 32;
+ }
+ accu += inout->as_uint32[7];
+ inout->as_uint32[7] = accu & 0x7ffffffful;
+}
+
+/// We are already using a packed radix 16 representation for fe25519. The real use for this function
+/// is for architectures that use more bits for storing a fe25519 in a representation where multiplication
+/// may be calculated more efficiently.
+/// Here we simply copy the data.
+static void
+fe25519_pack(
+ unsigned char out[32],
+ volatile fe25519* in
+)
+{
+ uint8 ctr;
+
+ fe25519_reduceCompletely(in);
+
+ for (ctr = 0; ctr < 32; ctr++)
+ {
+ out[ctr] = in->as_uint8[ctr];
+ }
+}
+
+// Note, that r and x are allowed to overlap!
+static void
+fe25519_invert_useProvidedScratchBuffers(
+ fe25519* r,
+ const fe25519* x,
+ fe25519* t0,
+ fe25519* t1,
+ fe25519* t2
+)
+{
+ fe25519 *z11 = r; // store z11 in r (in order to save one temporary).
+ fe25519 *z2_10_0 = t1;
+ fe25519 *z2_50_0 = t2;
+ fe25519 *z2_100_0 = z2_10_0;
+
+ uint8 i;
+
+ {
+ fe25519 *z2 = z2_50_0;
+
+ /* 2 */ fe25519_square(z2, x);
+ /* 4 */ fe25519_square(t0, z2);
+ /* 8 */ fe25519_square(t0, t0);
+ /* 9 */ fe25519_mul(z2_10_0, t0, x);
+ /* 11 */ fe25519_mul(z11, z2_10_0, z2);
+
+ // z2 is dead.
+ }
+
+ /* 22 */ fe25519_square(t0, z11);
+ /* 2^5 - 2^0 = 31 */ fe25519_mul(z2_10_0, t0, z2_10_0);
+
+ /* 2^6 - 2^1 */ fe25519_square(t0, z2_10_0);
+ /* 2^7 - 2^2 */ fe25519_square(t0, t0);
+ /* 2^8 - 2^3 */ fe25519_square(t0, t0);
+ /* 2^9 - 2^4 */ fe25519_square(t0, t0);
+ /* 2^10 - 2^5 */ fe25519_square(t0, t0);
+ /* 2^10 - 2^0 */ fe25519_mul(z2_10_0, t0, z2_10_0);
+
+ /* 2^11 - 2^1 */ fe25519_square(t0, z2_10_0);
+
+ /* 2^20 - 2^10 */ for (i = 1; i < 10; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^20 - 2^0 */ fe25519_mul(z2_50_0, t0, z2_10_0);
+
+ /* 2^21 - 2^1 */ fe25519_square(t0, z2_50_0);
+
+ /* 2^40 - 2^20 */ for (i = 1; i < 20; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^40 - 2^0 */ fe25519_mul(t0, t0, z2_50_0);
+
+ /* 2^41 - 2^1 */ fe25519_square(t0, t0);
+
+ /* 2^50 - 2^10 */ for (i = 1; i < 10; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^50 - 2^0 */ fe25519_mul(z2_50_0, t0, z2_10_0);
+
+ /* 2^51 - 2^1 */ fe25519_square(t0, z2_50_0);
+
+ /* 2^100 - 2^50 */ for (i = 1; i < 50; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^100 - 2^0 */ fe25519_mul(z2_100_0, t0, z2_50_0);
+
+ /* 2^101 - 2^1 */ fe25519_square(t0, z2_100_0);
+
+ /* 2^200 - 2^100 */ for (i = 1; i < 100; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^200 - 2^0 */ fe25519_mul(t0, t0, z2_100_0);
+
+ /* 2^250 - 2^50 */ for (i = 0; i < 50; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^250 - 2^0 */ fe25519_mul(t0, t0, z2_50_0);
+
+ /* 2^255 - 2^5 */ for (i = 0; i < 5; i ++)
+ {
+ fe25519_square(t0, t0);
+ }
+ /* 2^255 - 21 */ fe25519_mul(r, t0, z11);
+}
+
+static void
+fe25519_setzero(
+ fe25519* out
+)
+{
+ uint8 ctr;
+
+ for (ctr = 0; ctr < 8; ctr++)
+ {
+ out->as_uint32[ctr] = 0;
+ }
+}
+
+static void
+fe25519_setone(
+ fe25519* out
+)
+{
+ uint8 ctr;
+
+ out->as_uint32[0] = 1;
+
+ for (ctr = 1; ctr < 8; ctr++)
+ {
+ out->as_uint32[ctr] = 0;
+ }
+}
+
+/*
+static void
+swapPointersConditionally (void **p1, void **p2, uint8 condition)
+{
+ // Secure version of this code:
+ //
+ // if (condition)
+ // {
+ // void *temp;
+ // temp = *p2;
+ // *p2 = *p1;
+ // *p1 = temp;
+ // }
+
+ uintptr mask = condition;
+ uintptr val1 = (uintptr) *p1;
+ uintptr val2 = (uintptr) *p2;
+ uintptr temp = val2 ^ val1;
+
+ mask = (uintptr)( - (intptr) mask );
+ temp ^= mask & (temp ^ val1);
+ val1 ^= mask & (val1 ^ val2);
+ val2 ^= mask & (val2 ^ temp);
+
+ *p1 = (void *) val1;
+ *p2 = (void *) val2;
+}
+*/
+
+static void
+fe25519_cswap(
+ fe25519* in1,
+ fe25519* in2,
+ int condition
+)
+{
+ int32 mask = condition;
+ uint32 ctr;
+
+ mask = -mask;
+
+ for (ctr = 0; ctr < 8; ctr++)
+ {
+ uint32 val1 = in1->as_uint32[ctr];
+ uint32 val2 = in2->as_uint32[ctr];
+ uint32 temp = val1;
+
+ val1 ^= mask & (val2 ^ val1);
+ val2 ^= mask & (val2 ^ temp);
+
+
+ in1->as_uint32[ctr] = val1;
+ in2->as_uint32[ctr] = val2;
+ }
+}
+
+// ****************************************************
+// Scalarmultiplication implementation.
+// ****************************************************
+
+typedef struct _ST_curve25519ladderstepWorkingState
+{
+ // The base point in affine coordinates
+ fe25519 x0;
+
+ // The two working points p, q, in projective coordinates. Possibly randomized.
+ fe25519 xp;
+ fe25519 zp;
+ fe25519 xq;
+ fe25519 zq;
+
+ volatile UN_256bitValue s;
+
+ int nextScalarBitToProcess;
+ uint8 previousProcessedBit;
+
+#ifdef DH_SWAP_BY_POINTERS
+ fe25519 *pXp;
+ fe25519 *pZp;
+ fe25519 *pXq;
+ fe25519 *pZq;
+#endif
+
+} ST_curve25519ladderstepWorkingState;
+
+static void
+curve25519_ladderstep(
+ ST_curve25519ladderstepWorkingState* pState
+)
+{
+ // Implements the "ladd-1987-m-3" differential-addition-and-doubling formulas
+ // Source: 1987 Montgomery "Speeding the Pollard and elliptic curve methods of factorization", page 261,
+ // fifth and sixth displays, plus common-subexpression elimination.
+ //
+ // Notation from the explicit formulas database:
+ // (X2,Z2) corresponds to (xp,zp),
+ // (X3,Z3) corresponds to (xq,zq)
+ // Result (X4,Z4) (X5,Z5) expected in (xp,zp) and (xq,zq)
+ //
+ // A = X2+Z2; AA = A^2; B = X2-Z2; BB = B^2; E = AA-BB; C = X3+Z3; D = X3-Z3;
+ // DA = D*A; CB = C*B; t0 = DA+CB; t1 = t0^2; X5 = Z1*t1; t2 = DA-CB;
+ // t3 = t2^2; Z5 = X1*t3; X4 = AA*BB; t4 = a24*E; t5 = BB+t4; Z4 = E*t5 ;
+ //
+ // Re-Ordered for using less temporaries.
+
+ fe25519 t1, t2;
+
+ #ifdef DH_SWAP_BY_POINTERS
+ fe25519 *b1=pState->pXp; fe25519 *b2=pState->pZp;
+ fe25519 *b3=pState->pXq; fe25519 *b4=pState->pZq;
+ #else
+ fe25519 *b1=&pState->xp; fe25519 *b2=&pState->zp;
+ fe25519 *b3=&pState->xq; fe25519 *b4=&pState->zq;
+ #endif
+
+ fe25519 *b5= &t1; fe25519 *b6=&t2;
+
+ fe25519_add(b5,b1,b2); // A = X2+Z2
+ fe25519_sub(b6,b1,b2); // B = X2-Z2
+ fe25519_add(b1,b3,b4); // C = X3+Z3
+ fe25519_sub(b2,b3,b4); // D = X3-Z3
+ fe25519_mul(b3,b2,b5); // DA= D*A
+ fe25519_mul(b2,b1,b6); // CB= C*B
+ fe25519_add(b1,b2,b3); // T0= DA+CB
+ fe25519_sub(b4,b3,b2); // T2= DA-CB
+ fe25519_square(b3,b1); // X5==T1= T0^2
+ fe25519_square(b1,b4); // T3= t2^2
+ fe25519_mul(b4,b1,&pState->x0); // Z5=X1*t3
+ fe25519_square(b1,b5); // AA=A^2
+ fe25519_square(b5,b6); // BB=B^2
+ fe25519_sub(b2,b1,b5); // E=AA-BB
+ fe25519_mul(b1,b5,b1); // X4= AA*BB
+ fe25519_mpyWith121666 (b6,b2); // T4 = a24*E
+ fe25519_add(b6,b6,b5); // T5 = BB + t4
+ fe25519_mul(b2,b6,b2); // Z4 = E*t5
+}
+
+static void
+curve25519_cswap(
+ ST_curve25519ladderstepWorkingState* state,
+ uint8 b
+)
+{
+ #ifdef DH_SWAP_BY_POINTERS
+ swapPointersConditionally ((void **) &state->pXp,(void **) &state->pXq,b);
+ swapPointersConditionally ((void **) &state->pZp,(void **) &state->pZq,b);
+ #else
+ fe25519_cswap (&state->xp, &state->xq,b);
+ fe25519_cswap (&state->zp, &state->zq,b);
+ #endif
+}
+
+#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS
+
+static void
+curve25519_doublePointP (ST_curve25519ladderstepWorkingState* pState)
+{
+ // Implement the doubling formula "dbl-1987-m-3"
+ // from 1987 Montgomery "Speeding the Pollard and elliptic curve methods of factorization",
+ // page 261, sixth display, plus common-subexpression elimination.
+ //
+ // Three operand code:
+ // A = X1+Z1
+ // AA = A^2
+ // B = X1-Z1
+ // BB = B^2
+ // C = AA-BB
+ // X3 = AA*BB
+ // t0 = a24*C
+ // t1 = BB+t0
+ // Z3 = C*t1
+
+ // Double the point input in the state variable "P". Use the State variable "Q" as temporary
+ // for storing A, AA and B, BB. Use the same temporary variable for A and AA respectively and
+ // B, BB respectively.
+ #ifdef DH_SWAP_BY_POINTERS
+ fe25519 *pA = pState->pXq;
+ fe25519 *pB = pState->pZq;
+ fe25519 *pX = pState->pXp;
+ fe25519 *pZ = pState->pZp;
+ #else
+ fe25519 *pA = &pState->xq;
+ fe25519 *pB = &pState->zq;
+ fe25519 *pX = &pState->xp;
+ fe25519 *pZ = &pState->zp;
+ #endif
+
+ // A = X1+Z1
+ fe25519_add(pA, pX, pZ);
+ // AA = A^2
+ fe25519_square (pA,pA);
+ // B = X1-Z1
+ fe25519_sub(pB, pX, pZ);
+ // BB = B^2
+ fe25519_square (pB,pB);
+ // X3 = AA*BB
+ fe25519_mul (pX,pA,pB);
+ // C = AA-BB
+ fe25519_sub (pZ,pA,pB);
+ // t0 = a24*C
+ fe25519_mpyWith121666 (pA,pZ);
+ // t1 = BB+t0
+ fe25519_add (pB,pA,pB);
+ // Z3 = C*t1
+ fe25519_mul (pZ,pZ,pB);
+}
+
+#endif // #ifdef DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS
+
+int
+crypto_scalarmult_curve25519(
+ unsigned char* r,
+ const unsigned char* s,
+ const unsigned char* p
+)
+{
+ ST_curve25519ladderstepWorkingState state;
+ unsigned char i;
+
+
+ // Prepare the scalar within the working state buffer.
+ for (i = 0; i < 32; i++)
+ {
+ state.s.as_uint8 [i] = s[i];
+ }
+#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS
+ // Due to explicit final doubling for the last three bits instead of a full ladderstep,
+ // the following line is no longer necessary.
+#else
+ state.s.as_uint8 [0] &= 248;
+#endif
+ state.s.as_uint8 [31] &= 127;
+ state.s.as_uint8 [31] |= 64;
+
+ // Copy the affine x-axis of the base point to the state.
+ fe25519_unpack (&state.x0, p);
+
+ // Prepare the working points within the working state struct.
+
+ fe25519_setone (&state.zq);
+ fe25519_cpy (&state.xq, &state.x0);
+
+ fe25519_setone(&state.xp);
+ fe25519_setzero(&state.zp);
+
+ state.nextScalarBitToProcess = 254;
+
+#ifdef DH_SWAP_BY_POINTERS
+ // we need to initially assign the pointers correctly.
+ state.pXp = &state.xp;
+ state.pZp = &state.zp;
+ state.pXq = &state.xq;
+ state.pZq = &state.zq;
+#endif
+
+ state.previousProcessedBit = 0;
+
+#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS
+ // Process all the bits except for the last three where we explicitly double the result.
+ while (state.nextScalarBitToProcess >= 3)
+#else
+ // Process all the bits except for the last three where we explicitly double the result.
+ while (state.nextScalarBitToProcess >= 0)
+#endif
+ {
+ uint8 byteNo = state.nextScalarBitToProcess >> 3;
+ uint8 bitNo = state.nextScalarBitToProcess & 7;
+ uint8 bit;
+ uint8 swap;
+
+ bit = 1 & (state.s.as_uint8 [byteNo] >> bitNo);
+ swap = bit ^ state.previousProcessedBit;
+ state.previousProcessedBit = bit;
+ curve25519_cswap(&state, swap);
+ curve25519_ladderstep(&state);
+ state.nextScalarBitToProcess --;
+ }
+
+ curve25519_cswap(&state,state.previousProcessedBit);
+
+#if DH_REPLACE_LAST_THREE_LADDERSTEPS_WITH_DOUBLINGS
+ curve25519_doublePointP (&state);
+ curve25519_doublePointP (&state);
+ curve25519_doublePointP (&state);
+#endif
+
+#ifdef DH_SWAP_BY_POINTERS
+ // optimize for stack usage.
+ fe25519_invert_useProvidedScratchBuffers (state.pZp, state.pZp, state.pXq,state.pZq,&state.x0);
+ fe25519_mul(state.pXp, state.pXp, state.pZp);
+ fe25519_reduceCompletely(state.pXp);
+
+ fe25519_pack (r, state.pXp);
+#else
+ // optimize for stack usage.
+ fe25519_invert_useProvidedScratchBuffers (&state.zp, &state.zp, &state.xq, &state.zq, &state.x0);
+ fe25519_mul(&state.xp, &state.xp, &state.zp);
+ fe25519_reduceCompletely(&state.xp);
+
+ fe25519_pack (r, &state.xp);
+#endif
+
+ return 0;
+}
+
+int
+crypto_scalarmult_curve25519_base(
+ unsigned char* q,
+ const unsigned char* n
+)
+{
+ static const uint8 base[32] =
+ {
+ 9, 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
+ };
+
+ return crypto_scalarmult_curve25519(q, n, base);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s
new file mode 100644
index 00000000..3b190c92
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/arm/unacl/sqr.s
@@ -0,0 +1,777 @@
+ .align 2
+ .global square256_asm
+ .type square256_asm, %function
+square256_asm:
+ push {r4-r7,lr}
+ mov r2, r8
+ mov r3, r9
+ mov r4, r10
+ mov r5, r11
+ push {r0-r5}
+
+ mov r12, r0
+ mov r4, r1
+ ldm r4!, {r0-r3}
+ push {r4}
+ /////////BEGIN LOW PART //////////////////////
+ ///SQR 128, in r0-r3
+ mov r8, r2
+ mov r9, r3
+ eor r4, r4
+ sub r2, r0
+ sbc r3, r1
+ sbc r4, r4
+ eor r2, r4
+ eor r3, r4
+ sub r2, r4
+ sbc r3, r4
+ mov r10, r2
+ mov r11, r3
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r7, r7
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r7, r7
+ add r1, r0
+ adc r2, r3
+ adc r7, r3
+ mov r3, r12
+ stm r3!, {r0-r1}
+ push {r3}
+
+ mov r12, r0
+ mov r0, r8
+ mov r8, r1
+ mov r1, r9
+ mov r9, r2
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r4, r4
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r4, r4
+ add r1, r0
+ adc r2, r3
+ adc r3, r4
+ eor r4, r4
+ mov r6, r9
+ add r0, r6
+ adc r7, r1
+ adc r2, r4
+ adc r3, r4
+ mov r1, r11
+ mov r11, r0
+ mov r0, r10
+ mov r9, r2
+ mov r10,r3
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r4, r4
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r4, r4
+ add r1, r0
+ adc r2, r3
+ adc r3, r4
+ mov r6, r11
+ mov r4, r11
+ mov r5, r7
+ sub r6, r0
+ sbc r7, r1
+ sbc r4, r2
+ sbc r5, r3
+ eor r1, r1
+ sbc r1, r1
+ mov r2, r12
+ mov r3, r8
+ add r2, r6
+ adc r3, r7
+ mov r6, r9
+ mov r7, r10
+ adc r4, r6
+ adc r5, r7
+ adc r6, r1
+ adc r7, r1
+ //results r12, r8, r2-r7
+ /////////END LOW PART ////////////////////////
+ pop {r0,r1}
+ stm r0!, {r2, r3}
+ push {r0, r4-r7}
+ ldm r1, {r0-r3}
+ /////////BEGIN HIGH PART //////////////////////
+ ///SQR 128, in r0-r3
+ mov r8, r2
+ mov r9, r3
+ eor r4, r4
+ sub r2, r0
+ sbc r3, r1
+ sbc r4, r4
+ eor r2, r4
+ eor r3, r4
+ sub r2, r4
+ sbc r3, r4
+ mov r10, r2
+ mov r11, r3
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r7, r7
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r7, r7
+ add r1, r0
+ adc r2, r3
+ adc r7, r3
+ mov r12, r0
+ mov r0, r8
+ mov r8, r1
+ mov r1, r9
+ mov r9, r2
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r4, r4
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r4, r4
+ add r1, r0
+ adc r2, r3
+ adc r3, r4
+ eor r4, r4
+ mov r6, r9
+ add r0, r6
+ adc r7, r1
+ adc r2, r4
+ adc r3, r4
+ mov r1, r11
+ mov r11, r0
+ mov r0, r10
+ mov r9, r2
+ mov r10,r3
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r4, r4
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r4, r4
+ add r1, r0
+ adc r2, r3
+ adc r3, r4
+ mov r6, r11
+ mov r4, r11
+ mov r5, r7
+ sub r6, r0
+ sbc r7, r1
+ sbc r4, r2
+ sbc r5, r3
+ eor r1, r1
+ sbc r1, r1
+ mov r2, r12
+ mov r3, r8
+ add r2, r6
+ adc r3, r7
+ mov r6, r9
+ mov r7, r10
+ adc r4, r6
+ adc r5, r7
+ adc r6, r1
+ adc r7, r1
+ //results r12, r8, r2-r7
+ /////////END HIGH PART ////////////////////////
+ mov r0, r12
+ mov r1, r8
+ mov r8, r4
+ mov r9, r5
+ mov r10, r6
+ mov r11, r7
+ pop {r4}
+ mov r12, r4//str
+ pop {r4-r7}
+ add r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r7
+ mov r4, r12
+ stm r4!, {r0-r3}//low part
+ mov r4, r8
+ mov r5, r9
+ mov r6, r10
+ mov r7, r11
+ eor r0, r0
+ adc r4, r0
+ adc r5, r0
+ adc r6, r0
+ adc r7, r0
+ pop {r0, r1} //r0->out, r1, in
+ push {r0,r4-r7}
+ ldm r1, {r0-r7}
+ sub r0, r4
+ sbc r1, r5
+ sbc r2, r6
+ sbc r3, r7
+ sbc r4, r4
+ eor r0, r4
+ eor r1, r4
+ eor r2, r4
+ eor r3, r4
+ sub r0, r4
+ sbc r1, r4
+ sbc r2, r4
+ sbc r3, r4
+ //////////BEGIN MIDDLE PART////////////////
+ ///SQR 128, in r0-r3
+ mov r8, r2
+ mov r9, r3
+ eor r4, r4
+ sub r2, r0
+ sbc r3, r1
+ sbc r4, r4
+ eor r2, r4
+ eor r3, r4
+ sub r2, r4
+ sbc r3, r4
+ mov r10, r2
+ mov r11, r3
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r7, r7
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r7, r7
+ add r1, r0
+ adc r2, r3
+ adc r7, r3
+ mov r12, r0
+ mov r0, r8
+ mov r8, r1
+ mov r1, r9
+ mov r9, r2
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r4, r4
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r4, r4
+ add r1, r0
+ adc r2, r3
+ adc r3, r4
+ eor r4, r4
+ mov r6, r9
+ add r0, r6
+ adc r7, r1
+ adc r2, r4
+ adc r3, r4
+ mov r1, r11
+ mov r11, r0
+ mov r0, r10
+ mov r9, r2
+ mov r10,r3
+ //SQR64, in: r0, r1, out: r0-r3, used: r0-r6
+ mov r2, r0
+ eor r3, r3
+ sub r2, r1
+ sbc r3, r3
+ eor r2, r3
+ sub r2, r3
+ lsr r3, r0, #16
+ uxth r0, r0
+ mov r4, r0
+ mul r4, r3
+ mul r0, r0
+ mul r3, r3
+ lsr r5, r4, #16
+ lsl r4, #16
+ add r0, r4
+ adc r3, r5
+ add r0, r4
+ adc r3, r5
+ lsr r4, r1, #16
+ uxth r1, r1
+ mov r5, r1
+ mul r5, r4
+ mul r1, r1
+ mul r4, r4
+ eor r6, r6
+ add r1, r3
+ adc r4, r6
+ lsr r3, r5, #16
+ lsl r5, r5, #16
+ add r1, r5
+ adc r4, r3
+ add r1, r5
+ adc r3, r4
+ lsr r4, r2, #16
+ uxth r2, r2
+ mov r5, r2
+ mul r5, r4
+ mul r2, r2
+ mul r4, r4
+ lsr r6, r5, #16
+ lsl r5, #16
+ add r2, r5
+ adc r4, r6
+ add r5, r2
+ adc r6, r4
+ eor r4, r4
+ mov r2, r1
+ sub r1, r5
+ sbc r2, r6
+ sbc r4, r4
+ add r1, r0
+ adc r2, r3
+ adc r3, r4
+ mov r6, r11
+ mov r4, r11
+ mov r5, r7
+ sub r6, r0
+ sbc r7, r1
+ sbc r4, r2
+ sbc r5, r3
+ eor r1, r1
+ sbc r1, r1
+ mov r2, r12
+ mov r3, r8
+ add r2, r6
+ adc r3, r7
+ mov r6, r9
+ mov r7, r10
+ adc r4, r6
+ adc r5, r7
+ adc r6, r1
+ adc r7, r1
+ //results r12, r8, r2-r7
+ //////////END MIDDLE PART//////////////////
+ mvn r2, r2
+ mvn r3, r3
+ mvn r4, r4
+ mvn r5, r5
+ mvn r6, r6
+ mvn r7, r7
+ pop {r1}
+ push {r4-r7}
+ mov r4, #1
+ asr r4, #1
+ ldm r1!, {r4-r7}
+ mov r0, r12
+ mov r12, r1 ////////ref
+ mov r1, r8
+ mvn r0, r0
+ mvn r1, r1
+ adc r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r7
+ eor r4, r4
+ adc r4, r4
+ mov r8, r4 //carry A --ini
+ mov r4, r12
+ ldm r4, {r4-r7}
+ add r0, r4
+ adc r1, r5
+ adc r2, r6
+ adc r3, r7
+ mov r9, r4
+ mov r4, r12
+ stm r4!, {r0-r3}
+ mov r12, r4
+ mov r4, r9
+ pop {r0-r3}
+ adc r4, r0
+ adc r5, r1
+ adc r6, r2
+ adc r7, r3
+ eor r0, r0
+ adc r0, r0
+ mov r9, r0 //carry B --ini
+ mov r0, r8
+ asr r0, #1 //carry A --end
+ pop {r0-r3}
+ adc r4, r0
+ adc r5, r1
+ adc r6, r2
+ adc r7, r3
+ mov r8, r0
+ mov r0, r12
+ stm r0!, {r4-r7}
+ mov r11, r0
+ mov r0, r8
+ eor r4, r4
+ mov r5, r9
+ adc r5, r4 //carry B --end
+ mvn r6, r4
+ add r5, r6
+ adc r6, r4
+ add r0, r5
+ adc r1, r6
+ adc r2, r6
+ adc r3, r6
+ mov r7, r11
+ stm r7!, {r0-r3}
+
+ pop {r3-r6}
+ mov r8, r3
+ mov r9, r4
+ mov r10, r5
+ mov r11, r6
+ pop {r4-r7,pc}
+ bx lr
+ .size square256_asm, .-square256_asm
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/bitops.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/bitops.h
new file mode 100644
index 00000000..f2ca3084
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/bitops.h
@@ -0,0 +1,310 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef _WINDOWS
+#include <intrin.h>
+#endif
+
+/* Assorted bitwise and common operations used in ciphers. */
+
+/** Circularly rotate right x by n bits.
+ * 0 > n > 32. */
+static inline uint32_t rotr32(uint32_t x, unsigned n)
+{
+ return (x >> n) | (x << (32 - n));
+}
+
+/** Circularly rotate left x by n bits.
+ * 0 > n > 32. */
+static inline uint32_t rotl32(uint32_t x, unsigned n)
+{
+ return (x << n) | (x >> (32 - n));
+}
+
+/** Circularly rotate right x by n bits.
+ * 0 > n > 64. */
+static inline uint64_t rotr64(uint64_t x, unsigned n)
+{
+ return (x >> n) | (x << (64 - n));
+}
+
+/** Circularly rotate left x by n bits.
+ * 0 > n > 64. */
+static inline uint64_t rotl64(uint64_t x, unsigned n)
+{
+ return (x << n) | (x >> (64 - n));
+}
+
+/** Read 4 bytes from buf, as a 32-bit big endian quantity. */
+static inline uint32_t read32_be(const uint8_t buf[4])
+{
+ return (buf[0] << 24) |
+ (buf[1] << 16) |
+ (buf[2] << 8) |
+ (buf[3]);
+}
+
+/** Read 4 bytes from buf, as a 32-bit little endian quantity. */
+static inline uint32_t read32_le(const uint8_t buf[4])
+{
+ return (buf[3] << 24) |
+ (buf[2] << 16) |
+ (buf[1] << 8) |
+ (buf[0]);
+}
+
+/** Read 8 bytes from buf, as a 64-bit big endian quantity. */
+static inline uint64_t read64_be(const uint8_t buf[8])
+{
+ uint32_t hi = read32_be(buf),
+ lo = read32_be(buf + 4);
+ return ((uint64_t)hi) << 32 |
+ lo;
+}
+
+/** Read 8 bytes from buf, as a 64-bit little endian quantity. */
+static inline uint64_t read64_le(const uint8_t buf[8])
+{
+ uint32_t hi = read32_le(buf + 4),
+ lo = read32_le(buf);
+ return ((uint64_t)hi) << 32 |
+ lo;
+}
+
+/** Encode v as a 32-bit big endian quantity into buf. */
+static inline void write32_be(uint32_t v, uint8_t buf[4])
+{
+ *buf++ = (v >> 24) & 0xff;
+ *buf++ = (v >> 16) & 0xff;
+ *buf++ = (v >> 8) & 0xff;
+ *buf = v & 0xff;
+}
+
+/** Encode v as a 32-bit little endian quantity into buf. */
+static inline void write32_le(uint32_t v, uint8_t buf[4])
+{
+ *buf++ = v & 0xff;
+ *buf++ = (v >> 8) & 0xff;
+ *buf++ = (v >> 16) & 0xff;
+ *buf = (v >> 24) & 0xff;
+}
+
+/** Encode v as a 64-bit big endian quantity into buf. */
+static inline void write64_be(uint64_t v, uint8_t buf[8])
+{
+ *buf++ = (v >> 56) & 0xff;
+ *buf++ = (v >> 48) & 0xff;
+ *buf++ = (v >> 40) & 0xff;
+ *buf++ = (v >> 32) & 0xff;
+ *buf++ = (v >> 24) & 0xff;
+ *buf++ = (v >> 16) & 0xff;
+ *buf++ = (v >> 8) & 0xff;
+ *buf = v & 0xff;
+}
+
+/** Encode v as a 64-bit little endian quantity into buf. */
+static inline void write64_le(uint64_t v, uint8_t buf[8])
+{
+ *buf++ = v & 0xff;
+ *buf++ = (v >> 8) & 0xff;
+ *buf++ = (v >> 16) & 0xff;
+ *buf++ = (v >> 24) & 0xff;
+ *buf++ = (v >> 32) & 0xff;
+ *buf++ = (v >> 40) & 0xff;
+ *buf++ = (v >> 48) & 0xff;
+ *buf = (v >> 56) & 0xff;
+}
+
+/** out = in ^ b8.
+ * out and in may alias. */
+static inline void xor_b8(uint8_t *out, const uint8_t *in, uint8_t b8, size_t len)
+{
+ size_t i;
+ for (i = 0; i < len; i++)
+ out[i] = in[i] ^ b8;
+}
+
+/** out = x ^ y.
+ * out, x and y may alias. */
+static inline void xor_bb(uint8_t *out, const uint8_t *x, const uint8_t *y, size_t len)
+{
+ size_t i;
+ for (i = 0; i < len; i++)
+ out[i] = x[i] ^ y[i];
+}
+
+/* out ^= x
+ * out and x may alias. */
+static inline void xor_words(uint32_t *out, const uint32_t *x, size_t nwords)
+{
+ size_t i;
+ for (i = 0; i < nwords; i++)
+ out[i] ^= x[i];
+}
+
+/** Produce 0xffffffff if x == y, zero otherwise, without branching. */
+static inline uint32_t mask_u32(uint32_t x, uint32_t y)
+{
+ uint32_t diff = x ^ y;
+ uint32_t diff_is_zero = ~diff & (diff - 1);
+ return (uint32_t)(-(int32_t)(diff_is_zero >> 31));
+}
+
+/** Product 0xff if x == y, zero otherwise, without branching. */
+static inline uint8_t mask_u8(uint32_t x, uint32_t y)
+{
+ uint32_t diff = x ^ y;
+ uint8_t diff_is_zero = ~diff & (diff - 1);
+ return - (diff_is_zero >> 7);
+}
+
+/** Select the ith entry from the given table of n values, in a side channel-silent
+ * way. */
+static inline uint32_t select_u32(uint32_t i, volatile const uint32_t *tab, uint32_t n)
+{
+ uint32_t r = 0, ii;
+
+ for (ii = 0; ii < n; ii++)
+ {
+ uint32_t mask = mask_u32(i, ii);
+ r = (r & ~mask) | (tab[ii] & mask);
+ }
+
+ return r;
+}
+
+/** Select the ith entry from the given table of n values, in a side channel-silent
+ * way. */
+static inline uint8_t select_u8(uint32_t i, volatile const uint8_t *tab, uint32_t n)
+{
+ uint8_t r = 0;
+ uint32_t ii;
+
+ for (ii = 0; ii < n; ii++)
+ {
+ uint8_t mask = mask_u8(i, ii);
+ r = (r & ~mask) | (tab[ii] & mask);
+ }
+
+ return r;
+}
+
+/** Select the ath, bth, cth and dth entries from the given table of n values,
+ * placing the results into a, b, c and d. */
+static inline void select_u8x4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
+ volatile const uint8_t *tab, uint32_t n)
+{
+ uint8_t ra = 0,
+ rb = 0,
+ rc = 0,
+ rd = 0;
+ uint8_t mask;
+ uint32_t i;
+
+ for (i = 0; i < n; i++)
+ {
+ uint8_t item = tab[i];
+
+ mask = mask_u8(*a, i); ra = (ra & ~mask) | (item & mask);
+ mask = mask_u8(*b, i); rb = (rb & ~mask) | (item & mask);
+ mask = mask_u8(*c, i); rc = (rc & ~mask) | (item & mask);
+ mask = mask_u8(*d, i); rd = (rd & ~mask) | (item & mask);
+ }
+
+ *a = ra;
+ *b = rb;
+ *c = rc;
+ *d = rd;
+}
+
+/** out ^= if0 or if1, depending on the value of bit. */
+static inline void select_xor128(uint32_t out[4],
+ const uint32_t if0[4],
+ const uint32_t if1[4],
+ uint8_t bit)
+{
+ uint32_t mask1 = mask_u32(bit, 1);
+ uint32_t mask0 = ~mask1;
+
+ out[0] ^= (if0[0] & mask0) | (if1[0] & mask1);
+ out[1] ^= (if0[1] & mask0) | (if1[1] & mask1);
+ out[2] ^= (if0[2] & mask0) | (if1[2] & mask1);
+ out[3] ^= (if0[3] & mask0) | (if1[3] & mask1);
+}
+
+/** Increments the integer stored at v (of non-zero length len)
+ * with the least significant byte first. */
+static inline void incr_le(uint8_t *v, size_t len)
+{
+ size_t i = 0;
+ while (1)
+ {
+ if (++v[i] != 0)
+ return;
+ i++;
+ if (i == len)
+ return;
+ }
+}
+
+/** Increments the integer stored at v (of non-zero length len)
+ * with the most significant byte last. */
+static inline void incr_be(uint8_t *v, size_t len)
+{
+ len--;
+ while (1)
+ {
+ if (++v[len] != 0)
+ return;
+ if (len == 0)
+ return;
+ len--;
+ }
+}
+
+/** Copies len bytes from in to out, with in shifted left by offset bits
+ * to the right. */
+static inline void copy_bytes_unaligned(uint8_t *out, const uint8_t *in, size_t len, uint8_t offset)
+{
+ uint8_t byte_off = offset / 8;
+ uint8_t bit_off = offset & 7;
+ uint8_t rmask = (1 << bit_off) - 1;
+ uint8_t lmask = ~rmask;
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ {
+ out[i] = (in[i + byte_off] << bit_off) & lmask;
+ out[i] |= (in[i + byte_off + 1] >> (8 - bit_off)) & rmask;
+ }
+}
+
+static inline uint32_t count_trailing_zeroes(uint32_t x)
+{
+#ifdef _WINDOWS
+ uint32_t r = 0;
+ _BitScanReverse(&r, x);
+ return (31 - r);
+#else
+ return (uint32_t) __builtin_ctzl(x);
+#endif
+}
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.c
new file mode 100644
index 00000000..182c8c51
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.c
@@ -0,0 +1,195 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "blockwise.h"
+#include "bitops.h"
+#include "handy.h"
+#include "tassert.h"
+
+#include <string.h>
+
+void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial, size_t nblock,
+ const void *inp, size_t nbytes,
+ cf_blockwise_in_fn process,
+ void *ctx)
+{
+ cf_blockwise_accumulate_final(partial, npartial, nblock,
+ inp, nbytes,
+ process, process, ctx);
+}
+
+void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial, size_t nblock,
+ const void *inp, size_t nbytes,
+ cf_blockwise_in_fn process,
+ cf_blockwise_in_fn process_final,
+ void *ctx)
+{
+ const uint8_t *bufin = inp;
+ assert(partial && *npartial < nblock);
+ assert(inp || !nbytes);
+ assert(process && ctx);
+
+ /* If we have partial data, copy in to buffer. */
+ if (*npartial && nbytes)
+ {
+ size_t space = nblock - *npartial;
+ size_t taken = MIN(space, nbytes);
+
+ memcpy(partial + *npartial, bufin, taken);
+
+ bufin += taken;
+ nbytes -= taken;
+ *npartial += taken;
+
+ /* If that gives us a full block, process it. */
+ if (*npartial == nblock)
+ {
+ if (nbytes == 0)
+ process_final(ctx, partial);
+ else
+ process(ctx, partial);
+ *npartial = 0;
+ }
+ }
+
+ /* now nbytes < nblock or *npartial == 0. */
+
+ /* If we have a full block of data, process it directly. */
+ while (nbytes >= nblock)
+ {
+ /* Partial buffer must be empty, or we're ignoring extant data */
+ assert(*npartial == 0);
+
+ if (nbytes == nblock)
+ process_final(ctx, bufin);
+ else
+ process(ctx, bufin);
+ bufin += nblock;
+ nbytes -= nblock;
+ }
+
+ /* Finally, if we have remaining data, buffer it. */
+ while (nbytes)
+ {
+ size_t space = nblock - *npartial;
+ size_t taken = MIN(space, nbytes);
+
+ memcpy(partial + *npartial, bufin, taken);
+
+ bufin += taken;
+ nbytes -= taken;
+ *npartial += taken;
+
+ /* If we started with *npartial, we must have copied it
+ * in first. */
+ assert(*npartial < nblock);
+ }
+}
+
+void cf_blockwise_xor(uint8_t *partial, size_t *npartial, size_t nblock,
+ const void *inp, void *outp, size_t nbytes,
+ cf_blockwise_out_fn process, void *ctx)
+{
+ const uint8_t *inb = inp;
+ uint8_t *outb = outp;
+
+ assert(partial && *npartial < nblock);
+ assert(inp || !nbytes);
+ assert(process && ctx);
+
+ while (nbytes)
+ {
+ /* If we're out of material, and need more, produce a block. */
+ if (*npartial == 0)
+ {
+ process(ctx, partial);
+ *npartial = nblock;
+ }
+
+ size_t offset = nblock - *npartial;
+ size_t taken = MIN(*npartial, nbytes);
+ xor_bb(outb, inb, partial + offset, taken);
+ *npartial -= taken;
+ nbytes -= taken;
+ outb += taken;
+ inb += taken;
+ }
+}
+
+void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ uint8_t byte, size_t nbytes,
+ cf_blockwise_in_fn process,
+ void *ctx)
+{
+ /* only memset the whole of the block once */
+ int filled = 0;
+
+ while (nbytes)
+ {
+ size_t start = *npartial;
+ size_t count = MIN(nbytes, nblock - start);
+
+ if (!filled)
+ memset(partial + start, byte, count);
+
+ if (start == 0 && count == nblock)
+ filled = 1;
+
+ if (start + count == nblock)
+ {
+ process(ctx, partial);
+ *npartial = 0;
+ } else {
+ *npartial += count;
+ }
+
+ nbytes -= count;
+ }
+}
+
+void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ uint8_t fbyte, uint8_t mbyte, uint8_t lbyte,
+ size_t nbytes,
+ cf_blockwise_in_fn process,
+ void *ctx)
+{
+
+ switch (nbytes)
+ {
+ case 0: break;
+ case 1: fbyte ^= lbyte;
+ cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
+ break;
+ case 2:
+ cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
+ cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx);
+ break;
+ default:
+ cf_blockwise_accumulate(partial, npartial, nblock, &fbyte, 1, process, ctx);
+
+ /* If the middle and last bytes differ, then process the last byte separately.
+ * Otherwise, just extend the middle block size. */
+ if (lbyte != mbyte)
+ {
+ cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 2, process, ctx);
+ cf_blockwise_accumulate(partial, npartial, nblock, &lbyte, 1, process, ctx);
+ } else {
+ cf_blockwise_acc_byte(partial, npartial, nblock, mbyte, nbytes - 1, process, ctx);
+ }
+
+ break;
+ }
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.h
new file mode 100644
index 00000000..a20ff959
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/blockwise.h
@@ -0,0 +1,147 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef BLOCKWISE_H
+#define BLOCKWISE_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* Processing function for cf_blockwise_accumulate. */
+typedef void (*cf_blockwise_in_fn)(void *ctx, const uint8_t *data);
+
+/* Processing function for cf_blockwise_xor. */
+typedef void (*cf_blockwise_out_fn)(void *ctx, uint8_t *data);
+
+/* This function manages the common abstraction of accumulating input in
+ * a buffer, and processing it when a full block is available.
+ *
+ * partial is the buffer (maintained by the caller)
+ * on entry, npartial is the currently valid count of used bytes on
+ * the front of partial.
+ * on exit, npartial is updated to reflect the status of partial.
+ * nblock is the blocksize to accumulate -- partial must be at least
+ * this long!
+ * input is the new data to process, of length nbytes.
+ * process is the processing function, passed ctx and a pointer
+ * to the data to process (always exactly nblock bytes long!)
+ * which may not neccessarily be the same as partial.
+ */
+void cf_blockwise_accumulate(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ const void *input, size_t nbytes,
+ cf_blockwise_in_fn process,
+ void *ctx);
+
+/* This function manages the common abstraction of accumulating input in
+ * a buffer, and processing it when a full block is available.
+ * This version supports calling a different processing function for
+ * the last block.
+ *
+ * partial is the buffer (maintained by the caller)
+ * on entry, npartial is the currently valid count of used bytes on
+ * the front of partial.
+ * on exit, npartial is updated to reflect the status of partial.
+ * nblock is the blocksize to accumulate -- partial must be at least
+ * this long!
+ * input is the new data to process, of length nbytes.
+ * process is the processing function, passed ctx and a pointer
+ * to the data to process (always exactly nblock bytes long!)
+ * which may not neccessarily be the same as partial.
+ * process_final is called last (but may not be called at all if
+ * all input is buffered).
+ */
+void cf_blockwise_accumulate_final(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ const void *input, size_t nbytes,
+ cf_blockwise_in_fn process,
+ cf_blockwise_in_fn process_final,
+ void *ctx);
+
+/* This function manages XORing an input stream with a keystream
+ * to produce an output stream. The keystream is produced in blocks
+ * (ala a block cipher in counter mode).
+ *
+ * partial is the keystream buffer (maintained by the caller)
+ * on entry, *npartial is the currently valid count of bytes in partial:
+ * unused bytes are at the *end*. So *npartial = 4 means the last four
+ * bytes of partial are usable as keystream.
+ * on exit, npartial is updated to reflect the new state of partial.
+ * nblock is the blocksize to accumulate -- partial must be at least
+ * this long!
+ * input is the new data to process, of length nbytes.
+ * output is where to write input xored with the keystream -- also length
+ * nbytes.
+ * process is the processing function, passed ctx and partial which it
+ * should fill with fresh key stream.
+ */
+void cf_blockwise_xor(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ const void *input, void *output, size_t nbytes,
+ cf_blockwise_out_fn newblock,
+ void *ctx);
+
+/* This function processes a single byte a number of times. It's useful
+ * for padding, and more efficient than calling cf_blockwise_accumulate
+ * a bunch of times.
+ *
+ * partial is the buffer (maintained by the caller)
+ * on entry, npartial is the currently valid count of used bytes on
+ * the front of partial.
+ * on exit, npartial is updated to reflect the status of partial.
+ * nblock is the blocksize to accumulate -- partial must be at least
+ * this long!
+ * process is the processing function, passed ctx and a pointer
+ * to the data to process (always exactly nblock bytes long!)
+ * which may not neccessarily be the same as partial.
+ * byte is the byte to process, nbytes times.
+ */
+void cf_blockwise_acc_byte(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ uint8_t byte, size_t nbytes,
+ cf_blockwise_in_fn process,
+ void *ctx);
+
+/* This function attempts to process patterns of bytes common in
+ * block cipher padding.
+ *
+ * This takes three bytes:
+ * - a first byte, fbyte,
+ * - a middle byte, mbyte,
+ * - a last byte, lbyte.
+ *
+ * If nbytes is zero, nothing happens.
+ * If nbytes is one, the byte fbyte ^ lbyte is processed.
+ * If nbytes is two, the fbyte then lbyte are processed.
+ * If nbytes is three or more, fbyte, then one or more mbytes, then fbyte
+ * is processed.
+ *
+ * partial is the buffer (maintained by the caller)
+ * on entry, npartial is the currently valid count of used bytes on
+ * the front of partial.
+ * on exit, npartial is updated to reflect the status of partial.
+ * nblock is the blocksize to accumulate -- partial must be at least
+ * this long!
+ * process is the processing function, passed ctx and a pointer
+ * to the data to process (always exactly nblock bytes long!)
+ * which may not neccessarily be the same as partial.
+ */
+void cf_blockwise_acc_pad(uint8_t *partial, size_t *npartial,
+ size_t nblock,
+ uint8_t fbyte, uint8_t mbyte, uint8_t lbyte,
+ size_t nbytes,
+ cf_blockwise_in_fn process,
+ void *ctx);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cbcmac.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cbcmac.c
new file mode 100644
index 00000000..f0dfe875
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cbcmac.c
@@ -0,0 +1,79 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "bitops.h"
+#include "blockwise.h"
+#include "gf128.h"
+#include "tassert.h"
+
+#include <string.h>
+
+void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->prp = prp;
+ ctx->prpctx = prpctx;
+ cf_cbcmac_stream_reset(ctx);
+}
+
+void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx)
+{
+ uint8_t iv_zero[CF_MAXBLOCK] = { 0 };
+ cf_cbc_init(&ctx->cbc, ctx->prp, ctx->prpctx, iv_zero);
+ mem_clean(ctx->buffer, sizeof ctx->buffer);
+ ctx->used = 0;
+}
+
+static void cbcmac_process(void *vctx, const uint8_t *block)
+{
+ cf_cbcmac_stream *ctx = vctx;
+ uint8_t output[CF_MAXBLOCK];
+ cf_cbc_encrypt(&ctx->cbc, block, output, 1);
+}
+
+void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t len)
+{
+ cf_blockwise_accumulate(ctx->buffer, &ctx->used, ctx->prp->blocksz,
+ data, len,
+ cbcmac_process,
+ ctx);
+}
+
+void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx)
+{
+ if (ctx->used == 0)
+ return;
+
+ memset(ctx->buffer + ctx->used, 0, ctx->prp->blocksz - ctx->used);
+ cbcmac_process(ctx, ctx->buffer);
+ ctx->used = 0;
+}
+
+void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
+{
+ assert(ctx->used == 0);
+ memcpy(out, ctx->cbc.block, ctx->prp->blocksz);
+}
+
+void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
+{
+ uint8_t npad = ctx->prp->blocksz - ctx->used;
+ cf_blockwise_acc_byte(ctx->buffer, &ctx->used, ctx->prp->blocksz,
+ npad, npad,
+ cbcmac_process, ctx);
+ cf_cbcmac_stream_nopad_final(ctx, out);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ccm.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ccm.c
new file mode 100644
index 00000000..7ef87fc1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ccm.c
@@ -0,0 +1,193 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "tassert.h"
+
+#include <string.h>
+
+#define CCM_ADATA_PRESENT 0x40
+
+static void write_be(uint8_t *out, size_t value, size_t bytes)
+{
+ while (bytes)
+ {
+ out[bytes - 1] = value & 0xff;
+ value >>= 8;
+ bytes--;
+ }
+
+ assert(value == 0); /* or we couldn't encode the value. */
+}
+
+static void zero_pad(cf_cbcmac_stream *cm)
+{
+ cf_cbcmac_stream_finish_block_zero(cm);
+}
+
+/* nb. block is general workspace. */
+static void add_aad(cf_cbcmac_stream *cm, uint8_t block[CF_MAXBLOCK],
+ const uint8_t *header, size_t nheader)
+{
+ assert(nheader <= 0xffffffff); /* we don't support 64 bit lengths. */
+
+ /* Add length using stupidly complicated rules. */
+ if (nheader < 0xff00)
+ {
+ write_be(block, nheader, 2);
+ cf_cbcmac_stream_update(cm, block, 2);
+ } else {
+ write_be(block, 0xfffe, 2);
+ write_be(block + 2, nheader, 4);
+ cf_cbcmac_stream_update(cm, block, 6);
+ }
+
+ cf_cbcmac_stream_update(cm, header, nheader);
+ zero_pad(cm);
+}
+
+static void add_block0(cf_cbcmac_stream *cm,
+ uint8_t block[CF_MAXBLOCK], size_t nblock,
+ const uint8_t *nonce, size_t nnonce,
+ size_t L, size_t nplain,
+ size_t nheader, size_t ntag)
+{
+ /* Construct first block B_0. */
+ block[0] = ((nheader == 0) ? 0x00 : CCM_ADATA_PRESENT) |
+ ((ntag - 2) / 2) << 3 |
+ (L - 1);
+ memcpy(block + 1, nonce, nnonce);
+ write_be(block + 1 + nnonce, nplain, L);
+
+ cf_cbcmac_stream_update(cm, block, nblock);
+}
+
+static void build_ctr_nonce(uint8_t ctr_nonce[CF_MAXBLOCK],
+ size_t L,
+ const uint8_t *nonce, size_t nnonce)
+{
+ ctr_nonce[0] = (L - 1);
+ memcpy(ctr_nonce + 1, nonce, nnonce);
+ memset(ctr_nonce + 1 + nnonce, 0, L);
+}
+
+void cf_ccm_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain, size_t L,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher,
+ uint8_t *tag, size_t ntag)
+{
+ uint8_t block[CF_MAXBLOCK];
+
+ assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0);
+ assert(L >= 2 && L <= 8);
+ assert(nnonce == prp->blocksz - L - 1);
+
+ cf_cbcmac_stream cm;
+ cf_cbcmac_stream_init(&cm, prp, prpctx);
+
+ /* Add first block. */
+ add_block0(&cm, block, prp->blocksz,
+ nonce, nnonce,
+ L, nplain, nheader, ntag);
+
+ /* Add AAD with length prefix, if present. */
+ if (nheader)
+ add_aad(&cm, block, header, nheader);
+
+ /* Add message. */
+ cf_cbcmac_stream_update(&cm, plain, nplain);
+ zero_pad(&cm);
+
+ /* Finish tag. */
+ cf_cbcmac_stream_nopad_final(&cm, block);
+
+ /* Start encryption. */
+ /* Construct A_0 */
+ uint8_t ctr_nonce[CF_MAXBLOCK];
+ build_ctr_nonce(ctr_nonce, L, nonce, nnonce);
+
+ cf_ctr ctr;
+ cf_ctr_init(&ctr, prp, prpctx, ctr_nonce);
+ cf_ctr_custom_counter(&ctr, prp->blocksz - L, L);
+
+ /* Encrypt tag first. */
+ cf_ctr_cipher(&ctr, block, block, prp->blocksz);
+ memcpy(tag, block, ntag);
+
+ /* Then encrypt message. */
+ cf_ctr_cipher(&ctr, plain, cipher, nplain);
+}
+
+int cf_ccm_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher, size_t L,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain)
+{
+ uint8_t block[CF_MAXBLOCK];
+
+ assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0);
+ assert(L >= 2 && L <= 8);
+ assert(nnonce == prp->blocksz - L - 1);
+
+ uint8_t ctr_nonce[CF_MAXBLOCK];
+ build_ctr_nonce(ctr_nonce, L, nonce, nnonce);
+
+ cf_ctr ctr;
+ cf_ctr_init(&ctr, prp, prpctx, ctr_nonce);
+ cf_ctr_custom_counter(&ctr, prp->blocksz - L, L);
+
+ /* Decrypt tag. */
+ uint8_t plain_tag[CF_MAXBLOCK];
+ cf_ctr_cipher(&ctr, tag, plain_tag, ntag);
+ cf_ctr_discard_block(&ctr);
+
+ /* Decrypt message. */
+ cf_ctr_cipher(&ctr, cipher, plain, ncipher);
+
+ cf_cbcmac_stream cm;
+ cf_cbcmac_stream_init(&cm, prp, prpctx);
+
+ /* Add first block. */
+ add_block0(&cm, block, prp->blocksz,
+ nonce, nnonce,
+ L, ncipher, nheader, ntag);
+
+ if (nheader)
+ add_aad(&cm, block, header, nheader);
+
+ cf_cbcmac_stream_update(&cm, plain, ncipher);
+ zero_pad(&cm);
+
+ /* Finish tag. */
+ cf_cbcmac_stream_nopad_final(&cm, block);
+
+ int err = 0;
+
+ if (!mem_eq(block, plain_tag, ntag))
+ {
+ err = 1;
+ mem_clean(plain, ncipher);
+ }
+
+ mem_clean(block, sizeof block);
+ mem_clean(plain_tag, sizeof plain_tag);
+ return err;
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cf_config.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cf_config.h
new file mode 100644
index 00000000..ceb7e8da
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cf_config.h
@@ -0,0 +1,59 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef CF_CONFIG_H
+#define CF_CONFIG_H
+
+/**
+ * Library configuration
+ * =====================
+ */
+
+/* .. c:macro:: CF_SIDE_CHANNEL_PROTECTION
+ * Define this as 1 if you need all available side channel protections.
+ * **This option may alter the ABI**.
+ *
+ * This has a non-trivial performance penalty. Where a
+ * side-channel free option is cheap or free (like checking
+ * a MAC) this is always done in a side-channel free way.
+ *
+ * The default is **on** for all available protections.
+ */
+#ifndef CF_SIDE_CHANNEL_PROTECTION
+# define CF_SIDE_CHANNEL_PROTECTION 1
+#endif
+
+/* .. c:macro:: CF_TIME_SIDE_CHANNEL_PROTECTION
+ * Define this as 1 if you need timing/branch prediction side channel
+ * protection.
+ *
+ * You probably want this. The default is on. */
+#ifndef CF_TIME_SIDE_CHANNEL_PROTECTION
+# define CF_TIME_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION
+#endif
+
+/* .. c:macro:: CF_CACHE_SIDE_CHANNEL_PROTECTION
+ * Define this as 1 if you need cache side channel protection.
+ *
+ * If you have a microcontroller with no cache, you can turn this off
+ * without negative effects.
+ *
+ * The default is on. This will have some performance impact,
+ * especially on AES.
+ */
+#ifndef CF_CACHE_SIDE_CHANNEL_PROTECTION
+# define CF_CACHE_SIDE_CHANNEL_PROTECTION CF_SIDE_CHANNEL_PROTECTION
+#endif
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c
new file mode 100644
index 00000000..7a3bf382
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c
@@ -0,0 +1,161 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "bitops.h"
+#include "salsa20.h"
+#include "blockwise.h"
+#include "tassert.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+void cf_chacha20_core(const uint8_t key0[16],
+ const uint8_t key1[16],
+ const uint8_t nonce[16],
+ const uint8_t constant[16],
+ uint8_t out[64])
+{
+ uint32_t z0, z1, z2, z3, z4, z5, z6, z7,
+ z8, z9, za, zb, zc, zd, ze, zf;
+
+ uint32_t x0 = z0 = read32_le(constant + 0),
+ x1 = z1 = read32_le(constant + 4),
+ x2 = z2 = read32_le(constant + 8),
+ x3 = z3 = read32_le(constant + 12),
+ x4 = z4 = read32_le(key0 + 0),
+ x5 = z5 = read32_le(key0 + 4),
+ x6 = z6 = read32_le(key0 + 8),
+ x7 = z7 = read32_le(key0 + 12),
+ x8 = z8 = read32_le(key1 + 0),
+ x9 = z9 = read32_le(key1 + 4),
+ xa = za = read32_le(key1 + 8),
+ xb = zb = read32_le(key1 + 12),
+ xc = zc = read32_le(nonce + 0),
+ xd = zd = read32_le(nonce + 4),
+ xe = ze = read32_le(nonce + 8),
+ xf = zf = read32_le(nonce + 12);
+
+#define QUARTER(a, b, c, d) \
+ a += b; d = rotl32(d ^ a, 16); \
+ c += d; b = rotl32(b ^ c, 12); \
+ a += b; d = rotl32(d ^ a, 8); \
+ c += d; b = rotl32(b ^ c, 7);
+
+ int i;
+ for (i = 0; i < 10; i++)
+ {
+ QUARTER(z0, z4, z8, zc);
+ QUARTER(z1, z5, z9, zd);
+ QUARTER(z2, z6, za, ze);
+ QUARTER(z3, z7, zb, zf);
+ QUARTER(z0, z5, za, zf);
+ QUARTER(z1, z6, zb, zc);
+ QUARTER(z2, z7, z8, zd);
+ QUARTER(z3, z4, z9, ze);
+ }
+
+ x0 += z0;
+ x1 += z1;
+ x2 += z2;
+ x3 += z3;
+ x4 += z4;
+ x5 += z5;
+ x6 += z6;
+ x7 += z7;
+ x8 += z8;
+ x9 += z9;
+ xa += za;
+ xb += zb;
+ xc += zc;
+ xd += zd;
+ xe += ze;
+ xf += zf;
+
+ write32_le(x0, out + 0);
+ write32_le(x1, out + 4);
+ write32_le(x2, out + 8);
+ write32_le(x3, out + 12);
+ write32_le(x4, out + 16);
+ write32_le(x5, out + 20);
+ write32_le(x6, out + 24);
+ write32_le(x7, out + 28);
+ write32_le(x8, out + 32);
+ write32_le(x9, out + 36);
+ write32_le(xa, out + 40);
+ write32_le(xb, out + 44);
+ write32_le(xc, out + 48);
+ write32_le(xd, out + 52);
+ write32_le(xe, out + 56);
+ write32_le(xf, out + 60);
+}
+
+static const uint8_t *chacha20_tau = (const uint8_t *) "expand 16-byte k";
+static const uint8_t *chacha20_sigma = (const uint8_t *) "expand 32-byte k";
+
+static void set_key(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey)
+{
+ switch (nkey)
+ {
+ case 16:
+ memcpy(ctx->key0, key, 16);
+ memcpy(ctx->key1, key, 16);
+ ctx->constant = chacha20_tau;
+ break;
+ case 32:
+ memcpy(ctx->key0, key, 16);
+ memcpy(ctx->key1, key + 16, 16);
+ ctx->constant = chacha20_sigma;
+ break;
+ default:
+ abort();
+ }
+}
+
+void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8])
+{
+ set_key(ctx, key, nkey);
+ memset(ctx->nonce, 0, sizeof ctx->nonce);
+ memcpy(ctx->nonce + 8, nonce, 8);
+ ctx->nblock = 0;
+ ctx->ncounter = 8;
+}
+
+void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey,
+ const uint8_t nonce[16], size_t ncounter)
+{
+ assert(ncounter > 0);
+ set_key(ctx, key, nkey);
+ memcpy(ctx->nonce, nonce, sizeof ctx->nonce);
+ ctx->nblock = 0;
+ ctx->ncounter = ncounter;
+}
+
+static void cf_chacha20_next_block(void *vctx, uint8_t *out)
+{
+ cf_chacha20_ctx *ctx = vctx;
+ cf_chacha20_core(ctx->key0,
+ ctx->key1,
+ ctx->nonce,
+ ctx->constant,
+ out);
+ incr_le(ctx->nonce, ctx->ncounter);
+}
+
+void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes)
+{
+ cf_blockwise_xor(ctx->block, &ctx->nblock, 64,
+ input, output, bytes,
+ cf_chacha20_next_block,
+ ctx);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c
new file mode 100644
index 00000000..0aef7254
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.c
@@ -0,0 +1,148 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "chacha20poly1305.h"
+#include "salsa20.h"
+#include "poly1305.h"
+#include "bitops.h"
+#include "handy.h"
+
+#define ENCRYPT 1
+#define DECRYPT 0
+
+#define SUCCESS 0
+#define FAILURE 1
+
+static int process(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *input, size_t nbytes,
+ uint8_t *output,
+ int mode,
+ uint8_t tag[16])
+{
+ /* First, generate the Poly1305 key by running ChaCha20 with the
+ * given key and a zero counter. The first half of the
+ * 64-byte output is the key. */
+ uint8_t fullnonce[16] = { 0 };
+ memcpy(fullnonce + 4, nonce, 12);
+
+ uint8_t polykey[32] = { 0 };
+ cf_chacha20_ctx chacha;
+ cf_chacha20_init_custom(&chacha, key, 32, fullnonce, 4);
+ cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey);
+
+ /* Now initialise Poly1305. */
+ cf_poly1305 poly;
+ cf_poly1305_init(&poly, polykey, polykey + 16);
+ mem_clean(polykey, sizeof polykey);
+
+ /* Discard next 32 bytes of chacha20 key stream. */
+ cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey);
+ mem_clean(polykey, sizeof polykey);
+
+ /* The input to Poly1305 is:
+ * AAD || pad(AAD) || cipher || pad(cipher) || len_64(aad) || len_64(cipher) */
+ uint8_t padbuf[16] = { 0 };
+
+#define PADLEN(x) (16 - ((x) & 0xf))
+
+ /* AAD || pad(AAD) */
+ cf_poly1305_update(&poly, header, nheader);
+ cf_poly1305_update(&poly, padbuf, PADLEN(nheader));
+
+ /* || cipher */
+ if (mode == ENCRYPT)
+ {
+ /* If we're encrypting, we compute the ciphertext
+ * before inputting it into the MAC. */
+ cf_chacha20_cipher(&chacha, input, output, nbytes);
+ cf_poly1305_update(&poly, output, nbytes);
+ } else {
+ /* Otherwise: decryption -- input the ciphertext.
+ * Delay actual decryption until we checked the MAC. */
+ cf_poly1305_update(&poly, input, nbytes);
+ }
+
+ /* || pad(cipher) */
+ cf_poly1305_update(&poly, padbuf, PADLEN(nbytes));
+
+ /* || len_64(aad) || len_64(cipher) */
+ write64_le(nheader, padbuf);
+ write64_le(nbytes, padbuf + 8);
+ cf_poly1305_update(&poly, padbuf, sizeof padbuf);
+
+ /* MAC computation is now complete. */
+
+ if (mode == ENCRYPT)
+ {
+ cf_poly1305_finish(&poly, tag);
+ mem_clean(&chacha, sizeof chacha);
+ return SUCCESS;
+ }
+
+ /* Decrypt mode: calculate tag, and check it.
+ * If it's correct, proceed with decryption. */
+ uint8_t checktag[16];
+ cf_poly1305_finish(&poly, checktag);
+
+ if (mem_eq(checktag, tag, sizeof checktag))
+ {
+ cf_chacha20_cipher(&chacha, input, output, nbytes);
+ mem_clean(&chacha, sizeof chacha);
+ mem_clean(checktag, sizeof checktag);
+ return SUCCESS;
+ } else {
+ mem_clean(output, nbytes);
+ mem_clean(&chacha, sizeof chacha);
+ mem_clean(checktag, sizeof checktag);
+ return FAILURE;
+ }
+}
+
+void cf_chacha20poly1305_encrypt(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *plaintext, size_t nbytes,
+ uint8_t *ciphertext,
+ uint8_t tag[16])
+{
+ process(key,
+ nonce,
+ header, nheader,
+ plaintext, nbytes,
+ ciphertext,
+ ENCRYPT,
+ tag);
+}
+
+int cf_chacha20poly1305_decrypt(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *ciphertext, size_t nbytes,
+ const uint8_t tag[16],
+ uint8_t *plaintext)
+{
+ uint8_t ourtag[16];
+ memcpy(ourtag, tag, sizeof ourtag);
+
+ return process(key,
+ nonce,
+ header, nheader,
+ ciphertext, nbytes,
+ plaintext,
+ DECRYPT,
+ ourtag);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.h
new file mode 100644
index 00000000..1d44156c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20poly1305.h
@@ -0,0 +1,73 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef CHACHA20POLY1305_H
+#define CHACHA20POLY1305_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/**
+ * The ChaCha20-Poly1305 AEAD construction
+ * =======================================
+ * This is a composition of the ChaCha20 stream cipher and
+ * the Poly1305 polynomial MAC to form an AEAD.
+ * It's specified for use in TLS in the form of RFC7539.
+ *
+ * It uses a 256-bit key and a 96-bit nonce.
+ *
+ * This is a one-shot interface.
+ */
+
+/* .. c:function:: $DECL
+ * ChaCha20-Poly1305 authenticated encryption.
+ *
+ * :param key: key material.
+ * :param nonce: per-message nonce.
+ * :param header: header buffer.
+ * :param nheader: number of header bytes.
+ * :param plaintext: plaintext bytes to be encrypted.
+ * :param nbytes: number of plaintext/ciphertext bytes.
+ * :param ciphertext: ciphertext output buffer, nbytes in length.
+ * :param tag: authentication tag output buffer.
+ */
+void cf_chacha20poly1305_encrypt(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *plaintext, size_t nbytes,
+ uint8_t *ciphertext,
+ uint8_t tag[16]);
+
+/* .. c:function:: $DECL
+ * ChaCha20-Poly1305 authenticated decryption.
+ *
+ * :return: 0 on success, non-zero on error. Plaintext is zeroed on error.
+ *
+ * :param key: key material.
+ * :param nonce: per-message nonce.
+ * :param header: header buffer.
+ * :param nheader: number of header bytes.
+ * :param ciphertext: ciphertext bytes to be decrypted.
+ * :param nbytes: number of plaintext/ciphertext bytes.
+ * :param plaintext: plaintext output buffer, nbytes in length.
+ * :param tag: authentication tag output buffer.
+ */
+int cf_chacha20poly1305_decrypt(const uint8_t key[32],
+ const uint8_t nonce[12],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *ciphertext, size_t nbytes,
+ const uint8_t tag[16],
+ uint8_t *plaintext);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.c
new file mode 100644
index 00000000..4ee5d76e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.c
@@ -0,0 +1,28 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "chash.h"
+#include "handy.h"
+#include "tassert.h"
+
+void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out)
+{
+ cf_chash_ctx ctx;
+ assert(h);
+ h->init(&ctx);
+ h->update(&ctx, m, nm);
+ h->digest(&ctx, out);
+ mem_clean(&ctx, sizeof ctx);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.h
new file mode 100644
index 00000000..8f2e2012
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chash.h
@@ -0,0 +1,137 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef CHASH_H
+#define CHASH_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * General hash function description
+ * =================================
+ * This allows us to make use of hash functions without depending
+ * on a specific one. This is useful in implementing, for example,
+ * :doc:`HMAC <hmac>`.
+ */
+
+/* .. c:type:: cf_chash_init
+ * Hashing initialisation function type.
+ *
+ * Functions of this type should initialise the context in preparation
+ * for hashing a message with `cf_chash_update` functions.
+ *
+ * :rtype: void
+ * :param ctx: hash function-specific context structure.
+ */
+typedef void (*cf_chash_init)(void *ctx);
+
+/* .. c:type:: cf_chash_update
+ * Hashing data processing function type.
+ *
+ * Functions of this type hash `count` bytes of data at `data`,
+ * updating the contents of `ctx`.
+ *
+ * :rtype: void
+ * :param ctx: hash function-specific context structure.
+ * :param data: input data to hash.
+ * :param count: number of bytes to hash.
+ */
+typedef void (*cf_chash_update)(void *ctx, const void *data, size_t count);
+
+/* .. c:type:: cf_chash_digest
+ * Hashing completion function type.
+ *
+ * Functions of this type complete a hashing operation,
+ * writing :c:member:`cf_chash.hashsz` bytes to `hash`.
+ *
+ * This function does not change `ctx` -- any padding which needs doing
+ * must be done seperately (in a copy of `ctx`, say).
+ *
+ * This means you can interlave `_update` and `_digest` calls to
+ * learn `H(A)` and `H(A || B)` without hashing `A` twice.
+ *
+ * :rtype: void
+ * :param ctx: hash function-specific context structure.
+ * :param hash: location to write hash result.
+ */
+typedef void (*cf_chash_digest)(const void *ctx, uint8_t *hash);
+
+/* .. c:type:: cf_chash
+ * This type describes an incremental hash function in an abstract way.
+ *
+ * .. c:member:: cf_chash.hashsz
+ * The hash function's output, in bytes.
+ *
+ * .. c:member:: cf_chash.blocksz
+ * The hash function's internal block size, in bytes.
+ *
+ * .. c:member:: cf_chash.init
+ * Context initialisation function.
+ *
+ * .. c:member:: cf_chash:update
+ * Data processing function.
+ *
+ * .. c:member:: cf_chash:digest
+ * Completion function.
+ *
+ */
+typedef struct
+{
+ size_t hashsz;
+ size_t blocksz;
+
+ cf_chash_init init;
+ cf_chash_update update;
+ cf_chash_digest digest;
+} cf_chash;
+
+/* .. c:macro:: CF_CHASH_MAXCTX
+ * The maximum size of a :c:type:`cf_chash_ctx`. This allows
+ * use to put a structure in automatic storage that can
+ * store working data for any supported hash function. */
+#define CF_CHASH_MAXCTX 360
+
+/* .. c:macro:: CF_CHASH_MAXBLK
+ * Maximum hash function block size (in bytes). */
+#define CF_CHASH_MAXBLK 128
+
+/* .. c:macro:: CF_MAXHASH
+ * Maximum hash function output (in bytes). */
+#define CF_MAXHASH 64
+
+/* .. c:type:: cf_chash_ctx
+ * A type usable with any `cf_chash` as a context. */
+typedef union
+{
+ uint8_t ctx[CF_CHASH_MAXCTX];
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+} cf_chash_ctx;
+
+/* .. c:function:: $DECL
+ * One shot hashing: `out = h(m)`.
+ *
+ * Using the hash function `h`, `nm` bytes at `m` are hashed and `h->hashsz` bytes
+ * of result is written to the buffer `out`.
+ *
+ * :param h: hash function description.
+ * :param m: message buffer.
+ * :param nm: message length.
+ * :param out: hash result buffer (written).
+ */
+void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c
new file mode 100644
index 00000000..51f5843f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/cmac.c
@@ -0,0 +1,150 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "bitops.h"
+#include "blockwise.h"
+#include "gf128.h"
+#include "tassert.h"
+
+#include <string.h>
+
+void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx)
+{
+ uint8_t L[CF_MAXBLOCK];
+ assert(prp->blocksz == 16);
+
+ mem_clean(ctx, sizeof *ctx);
+
+ /* L = E_K(0^n) */
+ mem_clean(L, prp->blocksz);
+ prp->encrypt(prpctx, L, L);
+
+ /* B = 2L */
+ cf_gf128 gf;
+ cf_gf128_frombytes_be(L, gf);
+ cf_gf128_double(gf, gf);
+ cf_gf128_tobytes_be(gf, ctx->B);
+
+ /* P = 4L */
+ cf_gf128_double(gf, gf);
+ cf_gf128_tobytes_be(gf, ctx->P);
+
+ ctx->prp = prp;
+ ctx->prpctx = prpctx;
+}
+
+void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t len, uint8_t out[CF_MAXBLOCK])
+{
+ cf_cmac_stream stream;
+ stream.cmac = *ctx;
+ cf_cmac_stream_reset(&stream);
+ cf_cmac_stream_update(&stream, data, len, 1);
+ cf_cmac_stream_final(&stream, out);
+}
+
+void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx)
+{
+ cf_cmac_init(&ctx->cmac, prp, prpctx);
+ cf_cmac_stream_reset(ctx);
+}
+
+void cf_cmac_stream_reset(cf_cmac_stream *ctx)
+{
+ uint8_t iv_zero[CF_MAXBLOCK] = { 0 };
+ cf_cbc_init(&ctx->cbc, ctx->cmac.prp, ctx->cmac.prpctx, iv_zero);
+ mem_clean(ctx->buffer, sizeof ctx->buffer);
+ ctx->used = 0;
+ ctx->processed = 0;
+ ctx->finalised = 0;
+}
+
+static void cmac_process(void *vctx, const uint8_t *block)
+{
+ cf_cmac_stream *ctx = vctx;
+ uint8_t output[CF_MAXBLOCK];
+ cf_cbc_encrypt(&ctx->cbc, block, output, 1);
+ ctx->processed += ctx->cmac.prp->blocksz;
+}
+
+static void cmac_process_final(cf_cmac_stream *ctx, const uint8_t *block,
+ const uint8_t *xor)
+{
+ uint8_t input[CF_MAXBLOCK];
+ uint8_t output[CF_MAXBLOCK];
+ xor_bb(input, block, xor, ctx->cmac.prp->blocksz);
+ cf_cbc_encrypt(&ctx->cbc, input, output, 1);
+ ctx->processed += ctx->cmac.prp->blocksz;
+ /* signature is in ctx->cbc.block. */
+}
+
+static void cmac_process_final_nopad(void *vctx, const uint8_t *block)
+{
+ cf_cmac_stream *ctx = vctx;
+ cmac_process_final(ctx, block, ctx->cmac.B);
+ ctx->finalised = 1;
+}
+
+static void cmac_process_final_pad(void *vctx, const uint8_t *block)
+{
+ cf_cmac_stream *ctx = vctx;
+ cmac_process_final(ctx, block, ctx->cmac.P);
+ ctx->finalised = 1;
+}
+
+void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal)
+{
+ size_t blocksz = ctx->cmac.prp->blocksz;
+ cf_blockwise_in_fn final_fn = cmac_process;
+ int needpad = 0;
+
+ if (isfinal)
+ {
+ int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0;
+ int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0;
+
+ assert(!ctx->finalised); /* finalised before? */
+ assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */
+
+ /* If we have a whole number of blocks, and at least 1 block, we XOR in B.
+ * Otherwise, we need to pad and XOR in P. */
+ if (whole_number_of_blocks && !empty_message)
+ final_fn = cmac_process_final_nopad;
+ else
+ needpad = 1;
+ }
+
+ /* Input data */
+ cf_blockwise_accumulate_final(ctx->buffer, &ctx->used, blocksz,
+ data, len,
+ cmac_process,
+ final_fn, ctx);
+
+ /* Input padding */
+ if (needpad)
+ {
+ cf_blockwise_acc_pad(ctx->buffer, &ctx->used, blocksz,
+ 0x80, 0x00, 0x00, blocksz - ctx->used,
+ cmac_process_final_pad, ctx);
+ }
+}
+
+void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK])
+{
+ assert(ctx->finalised);
+ memcpy(out, ctx->cbc.block, ctx->cmac.prp->blocksz);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.c
new file mode 100644
index 00000000..6c4b9c15
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.c
@@ -0,0 +1,29 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#if defined(CORTEX_M0) || defined(CORTEX_M3) || defined(CORTEX_M4)
+#include "arm/unacl/scalarmult.c"
+
+void cf_curve25519_mul(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32])
+{
+ crypto_scalarmult_curve25519(out, scalar, point);
+}
+
+void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32])
+{
+ crypto_scalarmult_curve25519_base(out, scalar);
+}
+#else
+#include "curve25519.tweetnacl.c"
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.donna.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.donna.c
new file mode 100644
index 00000000..3c597d37
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.donna.c
@@ -0,0 +1,867 @@
+/* Copyright 2008, Google Inc.
+ * 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 Google Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * curve25519-donna: Curve25519 elliptic curve, public key function
+ *
+ * http://code.google.com/p/curve25519-donna/
+ *
+ * Adam Langley <agl@imperialviolet.org>
+ *
+ * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ * More information about curve25519 can be found here
+ * http://cr.yp.to/ecdh.html
+ *
+ * djb's sample implementation of curve25519 is written in a special assembly
+ * language called qhasm and uses the floating point registers.
+ *
+ * This is, almost, a clean room reimplementation from the curve25519 paper. It
+ * uses many of the tricks described therein. Only the crecip function is taken
+ * from the sample implementation. */
+
+#include "curve25519.h"
+
+#include <string.h>
+#include <stdint.h>
+
+#ifdef _MSC_VER
+#define inline __inline
+#endif
+
+typedef uint8_t u8;
+typedef int32_t s32;
+typedef int64_t limb;
+
+/* Field element representation:
+ *
+ * Field elements are written as an array of signed, 64-bit limbs, least
+ * significant first. The value of the field element is:
+ * x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
+ *
+ * i.e. the limbs are 26, 25, 26, 25, ... bits wide. */
+
+/* Sum two numbers: output += in */
+static void fsum(limb *output, const limb *in) {
+ unsigned i;
+ for (i = 0; i < 10; i += 2) {
+ output[0+i] = output[0+i] + in[0+i];
+ output[1+i] = output[1+i] + in[1+i];
+ }
+}
+
+/* Find the difference of two numbers: output = in - output
+ * (note the order of the arguments!). */
+static void fdifference(limb *output, const limb *in) {
+ unsigned i;
+ for (i = 0; i < 10; ++i) {
+ output[i] = in[i] - output[i];
+ }
+}
+
+/* Multiply a number by a scalar: output = in * scalar */
+static void fscalar_product(limb *output, const limb *in, const limb scalar) {
+ unsigned i;
+ for (i = 0; i < 10; ++i) {
+ output[i] = in[i] * scalar;
+ }
+}
+
+/* Multiply two numbers: output = in2 * in
+ *
+ * output must be distinct to both inputs. The inputs are reduced coefficient
+ * form, the output is not.
+ *
+ * output[x] <= 14 * the largest product of the input limbs. */
+static void fproduct(limb *output, const limb *in2, const limb *in) {
+ output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]);
+ output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[0]);
+ output[2] = 2 * ((limb) ((s32) in2[1])) * ((s32) in[1]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[2])) * ((s32) in[0]);
+ output[3] = ((limb) ((s32) in2[1])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[2])) * ((s32) in[1]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[0]);
+ output[4] = ((limb) ((s32) in2[2])) * ((s32) in[2]) +
+ 2 * (((limb) ((s32) in2[1])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[1])) +
+ ((limb) ((s32) in2[0])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[4])) * ((s32) in[0]);
+ output[5] = ((limb) ((s32) in2[2])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[4])) * ((s32) in[1]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[0]);
+ output[6] = 2 * (((limb) ((s32) in2[3])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[1])) +
+ ((limb) ((s32) in2[2])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[4])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[0]);
+ output[7] = ((limb) ((s32) in2[3])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[4])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[2])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[1]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[0]);
+ output[8] = ((limb) ((s32) in2[4])) * ((s32) in[4]) +
+ 2 * (((limb) ((s32) in2[3])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[1])) +
+ ((limb) ((s32) in2[2])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[0]);
+ output[9] = ((limb) ((s32) in2[4])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[2])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[2]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[1]) +
+ ((limb) ((s32) in2[0])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[0]);
+ output[10] = 2 * (((limb) ((s32) in2[5])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[1])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[1])) +
+ ((limb) ((s32) in2[4])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[2])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[2]);
+ output[11] = ((limb) ((s32) in2[5])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[4])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[4]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[3]) +
+ ((limb) ((s32) in2[2])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[2]);
+ output[12] = ((limb) ((s32) in2[6])) * ((s32) in[6]) +
+ 2 * (((limb) ((s32) in2[5])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[3])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[3])) +
+ ((limb) ((s32) in2[4])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[4]);
+ output[13] = ((limb) ((s32) in2[6])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[7])) * ((s32) in[6]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[5]) +
+ ((limb) ((s32) in2[4])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[4]);
+ output[14] = 2 * (((limb) ((s32) in2[7])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[5])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[5])) +
+ ((limb) ((s32) in2[6])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[6]);
+ output[15] = ((limb) ((s32) in2[7])) * ((s32) in[8]) +
+ ((limb) ((s32) in2[8])) * ((s32) in[7]) +
+ ((limb) ((s32) in2[6])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[6]);
+ output[16] = ((limb) ((s32) in2[8])) * ((s32) in[8]) +
+ 2 * (((limb) ((s32) in2[7])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[7]));
+ output[17] = ((limb) ((s32) in2[8])) * ((s32) in[9]) +
+ ((limb) ((s32) in2[9])) * ((s32) in[8]);
+ output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]);
+}
+
+/* Reduce a long form to a short form by taking the input mod 2^255 - 19.
+ *
+ * On entry: |output[i]| < 14*2^54
+ * On exit: |output[0..8]| < 280*2^54 */
+static void freduce_degree(limb *output) {
+ /* Each of these shifts and adds ends up multiplying the value by 19.
+ *
+ * For output[0..8], the absolute entry value is < 14*2^54 and we add, at
+ * most, 19*14*2^54 thus, on exit, |output[0..8]| < 280*2^54. */
+ output[8] += output[18] << 4;
+ output[8] += output[18] << 1;
+ output[8] += output[18];
+ output[7] += output[17] << 4;
+ output[7] += output[17] << 1;
+ output[7] += output[17];
+ output[6] += output[16] << 4;
+ output[6] += output[16] << 1;
+ output[6] += output[16];
+ output[5] += output[15] << 4;
+ output[5] += output[15] << 1;
+ output[5] += output[15];
+ output[4] += output[14] << 4;
+ output[4] += output[14] << 1;
+ output[4] += output[14];
+ output[3] += output[13] << 4;
+ output[3] += output[13] << 1;
+ output[3] += output[13];
+ output[2] += output[12] << 4;
+ output[2] += output[12] << 1;
+ output[2] += output[12];
+ output[1] += output[11] << 4;
+ output[1] += output[11] << 1;
+ output[1] += output[11];
+ output[0] += output[10] << 4;
+ output[0] += output[10] << 1;
+ output[0] += output[10];
+}
+
+#if (-1 & 3) != 3
+#error "This code only works on a two's complement system"
+#endif
+
+/* return v / 2^26, using only shifts and adds.
+ *
+ * On entry: v can take any value. */
+static inline limb
+div_by_2_26(const limb v)
+{
+ /* High word of v; no shift needed. */
+ const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
+ /* Set to all 1s if v was negative; else set to 0s. */
+ const int32_t sign = ((int32_t) highword) >> 31;
+ /* Set to 0x3ffffff if v was negative; else set to 0. */
+ const int32_t roundoff = ((uint32_t) sign) >> 6;
+ /* Should return v / (1<<26) */
+ return (v + roundoff) >> 26;
+}
+
+/* return v / (2^25), using only shifts and adds.
+ *
+ * On entry: v can take any value. */
+static inline limb
+div_by_2_25(const limb v)
+{
+ /* High word of v; no shift needed*/
+ const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
+ /* Set to all 1s if v was negative; else set to 0s. */
+ const int32_t sign = ((int32_t) highword) >> 31;
+ /* Set to 0x1ffffff if v was negative; else set to 0. */
+ const int32_t roundoff = ((uint32_t) sign) >> 7;
+ /* Should return v / (1<<25) */
+ return (v + roundoff) >> 25;
+}
+
+/* Reduce all coefficients of the short form input so that |x| < 2^26.
+ *
+ * On entry: |output[i]| < 280*2^54 */
+static void freduce_coefficients(limb *output) {
+ unsigned i;
+
+ output[10] = 0;
+
+ for (i = 0; i < 10; i += 2) {
+ limb over = div_by_2_26(output[i]);
+ /* The entry condition (that |output[i]| < 280*2^54) means that over is, at
+ * most, 280*2^28 in the first iteration of this loop. This is added to the
+ * next limb and we can approximate the resulting bound of that limb by
+ * 281*2^54. */
+ output[i] -= over << 26;
+ output[i+1] += over;
+
+ /* For the first iteration, |output[i+1]| < 281*2^54, thus |over| <
+ * 281*2^29. When this is added to the next limb, the resulting bound can
+ * be approximated as 281*2^54.
+ *
+ * For subsequent iterations of the loop, 281*2^54 remains a conservative
+ * bound and no overflow occurs. */
+ over = div_by_2_25(output[i+1]);
+ output[i+1] -= over << 25;
+ output[i+2] += over;
+ }
+ /* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */
+ output[0] += output[10] << 4;
+ output[0] += output[10] << 1;
+ output[0] += output[10];
+
+ output[10] = 0;
+
+ /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29
+ * So |over| will be no more than 2^16. */
+ {
+ limb over = div_by_2_26(output[0]);
+ output[0] -= over << 26;
+ output[1] += over;
+ }
+
+ /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The
+ * bound on |output[1]| is sufficient to meet our needs. */
+}
+
+/* A helpful wrapper around fproduct: output = in * in2.
+ *
+ * On entry: |in[i]| < 2^27 and |in2[i]| < 2^27.
+ *
+ * output must be distinct to both inputs. The output is reduced degree
+ * (indeed, one need only provide storage for 10 limbs) and |output[i]| < 2^26. */
+static void
+fmul(limb *output, const limb *in, const limb *in2) {
+ limb t[19];
+ fproduct(t, in, in2);
+ /* |t[i]| < 14*2^54 */
+ freduce_degree(t);
+ freduce_coefficients(t);
+ /* |t[i]| < 2^26 */
+ memcpy(output, t, sizeof(limb) * 10);
+}
+
+/* Square a number: output = in**2
+ *
+ * output must be distinct from the input. The inputs are reduced coefficient
+ * form, the output is not.
+ *
+ * output[x] <= 14 * the largest product of the input limbs. */
+static void fsquare_inner(limb *output, const limb *in) {
+ output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]);
+ output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]);
+ output[2] = 2 * (((limb) ((s32) in[1])) * ((s32) in[1]) +
+ ((limb) ((s32) in[0])) * ((s32) in[2]));
+ output[3] = 2 * (((limb) ((s32) in[1])) * ((s32) in[2]) +
+ ((limb) ((s32) in[0])) * ((s32) in[3]));
+ output[4] = ((limb) ((s32) in[2])) * ((s32) in[2]) +
+ 4 * ((limb) ((s32) in[1])) * ((s32) in[3]) +
+ 2 * ((limb) ((s32) in[0])) * ((s32) in[4]);
+ output[5] = 2 * (((limb) ((s32) in[2])) * ((s32) in[3]) +
+ ((limb) ((s32) in[1])) * ((s32) in[4]) +
+ ((limb) ((s32) in[0])) * ((s32) in[5]));
+ output[6] = 2 * (((limb) ((s32) in[3])) * ((s32) in[3]) +
+ ((limb) ((s32) in[2])) * ((s32) in[4]) +
+ ((limb) ((s32) in[0])) * ((s32) in[6]) +
+ 2 * ((limb) ((s32) in[1])) * ((s32) in[5]));
+ output[7] = 2 * (((limb) ((s32) in[3])) * ((s32) in[4]) +
+ ((limb) ((s32) in[2])) * ((s32) in[5]) +
+ ((limb) ((s32) in[1])) * ((s32) in[6]) +
+ ((limb) ((s32) in[0])) * ((s32) in[7]));
+ output[8] = ((limb) ((s32) in[4])) * ((s32) in[4]) +
+ 2 * (((limb) ((s32) in[2])) * ((s32) in[6]) +
+ ((limb) ((s32) in[0])) * ((s32) in[8]) +
+ 2 * (((limb) ((s32) in[1])) * ((s32) in[7]) +
+ ((limb) ((s32) in[3])) * ((s32) in[5])));
+ output[9] = 2 * (((limb) ((s32) in[4])) * ((s32) in[5]) +
+ ((limb) ((s32) in[3])) * ((s32) in[6]) +
+ ((limb) ((s32) in[2])) * ((s32) in[7]) +
+ ((limb) ((s32) in[1])) * ((s32) in[8]) +
+ ((limb) ((s32) in[0])) * ((s32) in[9]));
+ output[10] = 2 * (((limb) ((s32) in[5])) * ((s32) in[5]) +
+ ((limb) ((s32) in[4])) * ((s32) in[6]) +
+ ((limb) ((s32) in[2])) * ((s32) in[8]) +
+ 2 * (((limb) ((s32) in[3])) * ((s32) in[7]) +
+ ((limb) ((s32) in[1])) * ((s32) in[9])));
+ output[11] = 2 * (((limb) ((s32) in[5])) * ((s32) in[6]) +
+ ((limb) ((s32) in[4])) * ((s32) in[7]) +
+ ((limb) ((s32) in[3])) * ((s32) in[8]) +
+ ((limb) ((s32) in[2])) * ((s32) in[9]));
+ output[12] = ((limb) ((s32) in[6])) * ((s32) in[6]) +
+ 2 * (((limb) ((s32) in[4])) * ((s32) in[8]) +
+ 2 * (((limb) ((s32) in[5])) * ((s32) in[7]) +
+ ((limb) ((s32) in[3])) * ((s32) in[9])));
+ output[13] = 2 * (((limb) ((s32) in[6])) * ((s32) in[7]) +
+ ((limb) ((s32) in[5])) * ((s32) in[8]) +
+ ((limb) ((s32) in[4])) * ((s32) in[9]));
+ output[14] = 2 * (((limb) ((s32) in[7])) * ((s32) in[7]) +
+ ((limb) ((s32) in[6])) * ((s32) in[8]) +
+ 2 * ((limb) ((s32) in[5])) * ((s32) in[9]));
+ output[15] = 2 * (((limb) ((s32) in[7])) * ((s32) in[8]) +
+ ((limb) ((s32) in[6])) * ((s32) in[9]));
+ output[16] = ((limb) ((s32) in[8])) * ((s32) in[8]) +
+ 4 * ((limb) ((s32) in[7])) * ((s32) in[9]);
+ output[17] = 2 * ((limb) ((s32) in[8])) * ((s32) in[9]);
+ output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]);
+}
+
+/* fsquare sets output = in^2.
+ *
+ * On entry: The |in| argument is in reduced coefficients form and |in[i]| <
+ * 2^27.
+ *
+ * On exit: The |output| argument is in reduced coefficients form (indeed, one
+ * need only provide storage for 10 limbs) and |out[i]| < 2^26. */
+static void
+fsquare(limb *output, const limb *in) {
+ limb t[19];
+ fsquare_inner(t, in);
+ /* |t[i]| < 14*2^54 because the largest product of two limbs will be <
+ * 2^(27+27) and fsquare_inner adds together, at most, 14 of those
+ * products. */
+ freduce_degree(t);
+ freduce_coefficients(t);
+ /* |t[i]| < 2^26 */
+ memcpy(output, t, sizeof(limb) * 10);
+}
+
+/* Take a little-endian, 32-byte number and expand it into polynomial form */
+static void
+fexpand(limb *output, const u8 *input) {
+#define F(n,start,shift,mask) \
+ output[n] = ((((limb) input[start + 0]) | \
+ ((limb) input[start + 1]) << 8 | \
+ ((limb) input[start + 2]) << 16 | \
+ ((limb) input[start + 3]) << 24) >> shift) & mask;
+ F(0, 0, 0, 0x3ffffff);
+ F(1, 3, 2, 0x1ffffff);
+ F(2, 6, 3, 0x3ffffff);
+ F(3, 9, 5, 0x1ffffff);
+ F(4, 12, 6, 0x3ffffff);
+ F(5, 16, 0, 0x1ffffff);
+ F(6, 19, 1, 0x3ffffff);
+ F(7, 22, 3, 0x1ffffff);
+ F(8, 25, 4, 0x3ffffff);
+ F(9, 28, 6, 0x1ffffff);
+#undef F
+}
+
+#if (-32 >> 1) != -16
+#error "This code only works when >> does sign-extension on negative numbers"
+#endif
+
+/* s32_eq returns 0xffffffff iff a == b and zero otherwise. */
+static s32 s32_eq(s32 a, s32 b) {
+ a = ~(a ^ b);
+ a &= a << 16;
+ a &= a << 8;
+ a &= a << 4;
+ a &= a << 2;
+ a &= a << 1;
+ return a >> 31;
+}
+
+/* s32_gte returns 0xffffffff if a >= b and zero otherwise, where a and b are
+ * both non-negative. */
+static s32 s32_gte(s32 a, s32 b) {
+ a -= b;
+ /* a >= 0 iff a >= b. */
+ return ~(a >> 31);
+}
+
+/* Take a fully reduced polynomial form number and contract it into a
+ * little-endian, 32-byte array.
+ *
+ * On entry: |input_limbs[i]| < 2^26 */
+static void
+fcontract(u8 *output, limb *input_limbs) {
+ int i;
+ int j;
+ s32 input[10];
+ s32 mask;
+
+ /* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */
+ for (i = 0; i < 10; i++) {
+ input[i] = input_limbs[i];
+ }
+
+ for (j = 0; j < 2; ++j) {
+ for (i = 0; i < 9; ++i) {
+ if ((i & 1) == 1) {
+ /* This calculation is a time-invariant way to make input[i]
+ * non-negative by borrowing from the next-larger limb. */
+ const s32 mask = input[i] >> 31;
+ const s32 carry = -((input[i] & mask) >> 25);
+ input[i] = input[i] + (carry << 25);
+ input[i+1] = input[i+1] - carry;
+ } else {
+ const s32 mask = input[i] >> 31;
+ const s32 carry = -((input[i] & mask) >> 26);
+ input[i] = input[i] + (carry << 26);
+ input[i+1] = input[i+1] - carry;
+ }
+ }
+
+ /* There's no greater limb for input[9] to borrow from, but we can multiply
+ * by 19 and borrow from input[0], which is valid mod 2^255-19. */
+ {
+ const s32 mask = input[9] >> 31;
+ const s32 carry = -((input[9] & mask) >> 25);
+ input[9] = input[9] + (carry << 25);
+ input[0] = input[0] - (carry * 19);
+ }
+
+ /* After the first iteration, input[1..9] are non-negative and fit within
+ * 25 or 26 bits, depending on position. However, input[0] may be
+ * negative. */
+ }
+
+ /* The first borrow-propagation pass above ended with every limb
+ except (possibly) input[0] non-negative.
+
+ If input[0] was negative after the first pass, then it was because of a
+ carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most,
+ one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19.
+
+ In the second pass, each limb is decreased by at most one. Thus the second
+ borrow-propagation pass could only have wrapped around to decrease
+ input[0] again if the first pass left input[0] negative *and* input[1]
+ through input[9] were all zero. In that case, input[1] is now 2^25 - 1,
+ and this last borrow-propagation step will leave input[1] non-negative. */
+ {
+ const s32 mask = input[0] >> 31;
+ const s32 carry = -((input[0] & mask) >> 26);
+ input[0] = input[0] + (carry << 26);
+ input[1] = input[1] - carry;
+ }
+
+ /* All input[i] are now non-negative. However, there might be values between
+ * 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */
+ for (j = 0; j < 2; j++) {
+ for (i = 0; i < 9; i++) {
+ if ((i & 1) == 1) {
+ const s32 carry = input[i] >> 25;
+ input[i] &= 0x1ffffff;
+ input[i+1] += carry;
+ } else {
+ const s32 carry = input[i] >> 26;
+ input[i] &= 0x3ffffff;
+ input[i+1] += carry;
+ }
+ }
+
+ {
+ const s32 carry = input[9] >> 25;
+ input[9] &= 0x1ffffff;
+ input[0] += 19*carry;
+ }
+ }
+
+ /* If the first carry-chain pass, just above, ended up with a carry from
+ * input[9], and that caused input[0] to be out-of-bounds, then input[0] was
+ * < 2^26 + 2*19, because the carry was, at most, two.
+ *
+ * If the second pass carried from input[9] again then input[0] is < 2*19 and
+ * the input[9] -> input[0] carry didn't push input[0] out of bounds. */
+
+ /* It still remains the case that input might be between 2^255-19 and 2^255.
+ * In this case, input[1..9] must take their maximum value and input[0] must
+ * be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */
+ mask = s32_gte(input[0], 0x3ffffed);
+ for (i = 1; i < 10; i++) {
+ if ((i & 1) == 1) {
+ mask &= s32_eq(input[i], 0x1ffffff);
+ } else {
+ mask &= s32_eq(input[i], 0x3ffffff);
+ }
+ }
+
+ /* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus
+ * this conditionally subtracts 2^255-19. */
+ input[0] -= mask & 0x3ffffed;
+
+ for (i = 1; i < 10; i++) {
+ if ((i & 1) == 1) {
+ input[i] -= mask & 0x1ffffff;
+ } else {
+ input[i] -= mask & 0x3ffffff;
+ }
+ }
+
+ input[1] <<= 2;
+ input[2] <<= 3;
+ input[3] <<= 5;
+ input[4] <<= 6;
+ input[6] <<= 1;
+ input[7] <<= 3;
+ input[8] <<= 4;
+ input[9] <<= 6;
+#define F(i, s) \
+ output[s+0] |= input[i] & 0xff; \
+ output[s+1] = (input[i] >> 8) & 0xff; \
+ output[s+2] = (input[i] >> 16) & 0xff; \
+ output[s+3] = (input[i] >> 24) & 0xff;
+ output[0] = 0;
+ output[16] = 0;
+ F(0,0);
+ F(1,3);
+ F(2,6);
+ F(3,9);
+ F(4,12);
+ F(5,16);
+ F(6,19);
+ F(7,22);
+ F(8,25);
+ F(9,28);
+#undef F
+}
+
+/* Input: Q, Q', Q-Q'
+ * Output: 2Q, Q+Q'
+ *
+ * x2 z3: long form
+ * x3 z3: long form
+ * x z: short form, destroyed
+ * xprime zprime: short form, destroyed
+ * qmqp: short form, preserved
+ *
+ * On entry and exit, the absolute value of the limbs of all inputs and outputs
+ * are < 2^26. */
+static void fmonty(limb *x2, limb *z2, /* output 2Q */
+ limb *x3, limb *z3, /* output Q + Q' */
+ limb *x, limb *z, /* input Q */
+ limb *xprime, limb *zprime, /* input Q' */
+ const limb *qmqp /* input Q - Q' */) {
+ limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
+ zzprime[19], zzzprime[19], xxxprime[19];
+
+ memcpy(origx, x, 10 * sizeof(limb));
+ fsum(x, z);
+ /* |x[i]| < 2^27 */
+ fdifference(z, origx); /* does x - z */
+ /* |z[i]| < 2^27 */
+
+ memcpy(origxprime, xprime, sizeof(limb) * 10);
+ fsum(xprime, zprime);
+ /* |xprime[i]| < 2^27 */
+ fdifference(zprime, origxprime);
+ /* |zprime[i]| < 2^27 */
+ fproduct(xxprime, xprime, z);
+ /* |xxprime[i]| < 14*2^54: the largest product of two limbs will be <
+ * 2^(27+27) and fproduct adds together, at most, 14 of those products.
+ * (Approximating that to 2^58 doesn't work out.) */
+ fproduct(zzprime, x, zprime);
+ /* |zzprime[i]| < 14*2^54 */
+ freduce_degree(xxprime);
+ freduce_coefficients(xxprime);
+ /* |xxprime[i]| < 2^26 */
+ freduce_degree(zzprime);
+ freduce_coefficients(zzprime);
+ /* |zzprime[i]| < 2^26 */
+ memcpy(origxprime, xxprime, sizeof(limb) * 10);
+ fsum(xxprime, zzprime);
+ /* |xxprime[i]| < 2^27 */
+ fdifference(zzprime, origxprime);
+ /* |zzprime[i]| < 2^27 */
+ fsquare(xxxprime, xxprime);
+ /* |xxxprime[i]| < 2^26 */
+ fsquare(zzzprime, zzprime);
+ /* |zzzprime[i]| < 2^26 */
+ fproduct(zzprime, zzzprime, qmqp);
+ /* |zzprime[i]| < 14*2^52 */
+ freduce_degree(zzprime);
+ freduce_coefficients(zzprime);
+ /* |zzprime[i]| < 2^26 */
+ memcpy(x3, xxxprime, sizeof(limb) * 10);
+ memcpy(z3, zzprime, sizeof(limb) * 10);
+
+ fsquare(xx, x);
+ /* |xx[i]| < 2^26 */
+ fsquare(zz, z);
+ /* |zz[i]| < 2^26 */
+ fproduct(x2, xx, zz);
+ /* |x2[i]| < 14*2^52 */
+ freduce_degree(x2);
+ freduce_coefficients(x2);
+ /* |x2[i]| < 2^26 */
+ fdifference(zz, xx); // does zz = xx - zz
+ /* |zz[i]| < 2^27 */
+ memset(zzz + 10, 0, sizeof(limb) * 9);
+ fscalar_product(zzz, zz, 121665);
+ /* |zzz[i]| < 2^(27+17) */
+ /* No need to call freduce_degree here:
+ fscalar_product doesn't increase the degree of its input. */
+ freduce_coefficients(zzz);
+ /* |zzz[i]| < 2^26 */
+ fsum(zzz, xx);
+ /* |zzz[i]| < 2^27 */
+ fproduct(z2, zz, zzz);
+ /* |z2[i]| < 14*2^(26+27) */
+ freduce_degree(z2);
+ freduce_coefficients(z2);
+ /* |z2|i| < 2^26 */
+}
+
+/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave
+ * them unchanged if 'iswap' is 0. Runs in data-invariant time to avoid
+ * side-channel attacks.
+ *
+ * NOTE that this function requires that 'iswap' be 1 or 0; other values give
+ * wrong results. Also, the two limb arrays must be in reduced-coefficient,
+ * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,
+ * and all all values in a[0..9],b[0..9] must have magnitude less than
+ * INT32_MAX. */
+static void
+swap_conditional(limb a[19], limb b[19], limb iswap) {
+ unsigned i;
+ const s32 swap = (s32) -iswap;
+
+ for (i = 0; i < 10; ++i) {
+ const s32 x = swap & ( ((s32)a[i]) ^ ((s32)b[i]) );
+ a[i] = ((s32)a[i]) ^ x;
+ b[i] = ((s32)b[i]) ^ x;
+ }
+}
+
+/* Calculates nQ where Q is the x-coordinate of a point on the curve
+ *
+ * resultx/resultz: the x coordinate of the resulting curve point (short form)
+ * n: a little endian, 32-byte number
+ * q: a point of the curve (short form) */
+static void
+cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
+ limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
+ limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
+ limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
+ limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
+
+ unsigned i, j;
+
+ memcpy(nqpqx, q, sizeof(limb) * 10);
+
+ for (i = 0; i < 32; ++i) {
+ u8 byte = n[31 - i];
+ for (j = 0; j < 8; ++j) {
+ const limb bit = byte >> 7;
+
+ swap_conditional(nqx, nqpqx, bit);
+ swap_conditional(nqz, nqpqz, bit);
+ fmonty(nqx2, nqz2,
+ nqpqx2, nqpqz2,
+ nqx, nqz,
+ nqpqx, nqpqz,
+ q);
+ swap_conditional(nqx2, nqpqx2, bit);
+ swap_conditional(nqz2, nqpqz2, bit);
+
+ t = nqx;
+ nqx = nqx2;
+ nqx2 = t;
+ t = nqz;
+ nqz = nqz2;
+ nqz2 = t;
+ t = nqpqx;
+ nqpqx = nqpqx2;
+ nqpqx2 = t;
+ t = nqpqz;
+ nqpqz = nqpqz2;
+ nqpqz2 = t;
+
+ byte <<= 1;
+ }
+ }
+
+ memcpy(resultx, nqx, sizeof(limb) * 10);
+ memcpy(resultz, nqz, sizeof(limb) * 10);
+}
+
+// -----------------------------------------------------------------------------
+// Shamelessly copied from djb's code
+// -----------------------------------------------------------------------------
+static void
+crecip(limb *out, const limb *z) {
+ limb z2[10];
+ limb z9[10];
+ limb z11[10];
+ limb z2_5_0[10];
+ limb z2_10_0[10];
+ limb z2_20_0[10];
+ limb z2_50_0[10];
+ limb z2_100_0[10];
+ limb t0[10];
+ limb t1[10];
+ int i;
+
+ /* 2 */ fsquare(z2,z);
+ /* 4 */ fsquare(t1,z2);
+ /* 8 */ fsquare(t0,t1);
+ /* 9 */ fmul(z9,t0,z);
+ /* 11 */ fmul(z11,z9,z2);
+ /* 22 */ fsquare(t0,z11);
+ /* 2^5 - 2^0 = 31 */ fmul(z2_5_0,t0,z9);
+
+ /* 2^6 - 2^1 */ fsquare(t0,z2_5_0);
+ /* 2^7 - 2^2 */ fsquare(t1,t0);
+ /* 2^8 - 2^3 */ fsquare(t0,t1);
+ /* 2^9 - 2^4 */ fsquare(t1,t0);
+ /* 2^10 - 2^5 */ fsquare(t0,t1);
+ /* 2^10 - 2^0 */ fmul(z2_10_0,t0,z2_5_0);
+
+ /* 2^11 - 2^1 */ fsquare(t0,z2_10_0);
+ /* 2^12 - 2^2 */ fsquare(t1,t0);
+ /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^20 - 2^0 */ fmul(z2_20_0,t1,z2_10_0);
+
+ /* 2^21 - 2^1 */ fsquare(t0,z2_20_0);
+ /* 2^22 - 2^2 */ fsquare(t1,t0);
+ /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^40 - 2^0 */ fmul(t0,t1,z2_20_0);
+
+ /* 2^41 - 2^1 */ fsquare(t1,t0);
+ /* 2^42 - 2^2 */ fsquare(t0,t1);
+ /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
+ /* 2^50 - 2^0 */ fmul(z2_50_0,t0,z2_10_0);
+
+ /* 2^51 - 2^1 */ fsquare(t0,z2_50_0);
+ /* 2^52 - 2^2 */ fsquare(t1,t0);
+ /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^100 - 2^0 */ fmul(z2_100_0,t1,z2_50_0);
+
+ /* 2^101 - 2^1 */ fsquare(t1,z2_100_0);
+ /* 2^102 - 2^2 */ fsquare(t0,t1);
+ /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fsquare(t1,t0); fsquare(t0,t1); }
+ /* 2^200 - 2^0 */ fmul(t1,t0,z2_100_0);
+
+ /* 2^201 - 2^1 */ fsquare(t0,t1);
+ /* 2^202 - 2^2 */ fsquare(t1,t0);
+ /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fsquare(t0,t1); fsquare(t1,t0); }
+ /* 2^250 - 2^0 */ fmul(t0,t1,z2_50_0);
+
+ /* 2^251 - 2^1 */ fsquare(t1,t0);
+ /* 2^252 - 2^2 */ fsquare(t0,t1);
+ /* 2^253 - 2^3 */ fsquare(t1,t0);
+ /* 2^254 - 2^4 */ fsquare(t0,t1);
+ /* 2^255 - 2^5 */ fsquare(t1,t0);
+ /* 2^255 - 21 */ fmul(out,t1,z11);
+}
+
+void cf_curve25519_mul(u8 out[32], const u8 scalar[32], const u8 point[32])
+{
+ limb bp[10], x[10], z[11], zmone[10];
+ uint8_t e[32];
+ int i;
+
+ for (i = 0; i < 32; ++i) e[i] = scalar[i];
+ e[0] &= 248;
+ e[31] &= 127;
+ e[31] |= 64;
+
+ fexpand(bp, point);
+ cmult(x, z, e, bp);
+ crecip(zmone, z);
+ fmul(z, x, zmone);
+ fcontract(out, z);
+}
+
+void cf_curve25519_mul_base(u8 out[32], const u8 scalar[32])
+{
+ uint8_t base[32] = { 9 };
+ cf_curve25519_mul(out, scalar, base);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.h
new file mode 100644
index 00000000..9b0b7f54
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.h
@@ -0,0 +1,42 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef CURVE25519_H
+#define CURVE25519_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * Curve25519
+ * ==========
+ * This is `curve25519 <http://cr.yp.to/ecdh.html>`_ with switchable
+ * implementations underneath.
+ *
+ * By default tweetnacl is used on hosts, and the implementation
+ * from μNaCl for Cortex-M0, M3 and M4.
+ */
+
+/* .. c:function:: $DECL
+ * Multiplies `point` by `scalar`, putting the resulting point into `out`. */
+void cf_curve25519_mul(uint8_t out[32],
+ const uint8_t scalar[32],
+ const uint8_t point[32]);
+
+/* .. c:function:: $DECL
+ * Multiplies `scalar` by the curve25519 base point, putting the resulting
+ * point into `out`. */
+void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32]);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.naclref.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.naclref.c
new file mode 100644
index 00000000..9f331d1d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.naclref.c
@@ -0,0 +1,273 @@
+/*
+version 20081011
+Matthew Dempsky
+Public domain.
+Derived from public domain code by D. J. Bernstein.
+*/
+#include "curve25519.h"
+
+static void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32])
+{
+ unsigned int j;
+ unsigned int u;
+ u = 0;
+ for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; }
+ u += a[31] + b[31]; out[31] = u;
+}
+
+static void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32])
+{
+ unsigned int j;
+ unsigned int u;
+ u = 218;
+ for (j = 0;j < 31;++j) {
+ u += a[j] + 65280 - b[j];
+ out[j] = u & 255;
+ u >>= 8;
+ }
+ u += a[31] - b[31];
+ out[31] = u;
+}
+
+static void squeeze(unsigned int a[32])
+{
+ unsigned int j;
+ unsigned int u;
+ u = 0;
+ for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; }
+ u += a[31]; a[31] = u & 127;
+ u = 19 * (u >> 7);
+ for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; }
+ u += a[31]; a[31] = u;
+}
+
+static const unsigned int minusp[32] = {
+ 19, 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, 128
+} ;
+
+static void freeze(unsigned int a[32])
+{
+ unsigned int aorig[32];
+ unsigned int j;
+ unsigned int negative;
+
+ for (j = 0;j < 32;++j) aorig[j] = a[j];
+ add(a,a,minusp);
+ negative = -((a[31] >> 7) & 1);
+ for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]);
+}
+
+static void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32])
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int u;
+
+ for (i = 0;i < 32;++i) {
+ u = 0;
+ for (j = 0;j <= i;++j) u += a[j] * b[i - j];
+ for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j];
+ out[i] = u;
+ }
+ squeeze(out);
+}
+
+static void mult121665(unsigned int out[32],const unsigned int a[32])
+{
+ unsigned int j;
+ unsigned int u;
+
+ u = 0;
+ for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; }
+ u += 121665 * a[31]; out[31] = u & 127;
+ u = 19 * (u >> 7);
+ for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; }
+ u += out[j]; out[j] = u;
+}
+
+static void square(unsigned int out[32],const unsigned int a[32])
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int u;
+
+ for (i = 0;i < 32;++i) {
+ u = 0;
+ for (j = 0;j < i - j;++j) u += a[j] * a[i - j];
+ for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j];
+ u *= 2;
+ if ((i & 1) == 0) {
+ u += a[i / 2] * a[i / 2];
+ u += 38 * a[i / 2 + 16] * a[i / 2 + 16];
+ }
+ out[i] = u;
+ }
+ squeeze(out);
+}
+
+static void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b)
+{
+ unsigned int j;
+ unsigned int t;
+ unsigned int bminus1;
+
+ bminus1 = b - 1;
+ for (j = 0;j < 64;++j) {
+ t = bminus1 & (r[j] ^ s[j]);
+ p[j] = s[j] ^ t;
+ q[j] = r[j] ^ t;
+ }
+}
+
+static void mainloop(unsigned int work[64],const unsigned char e[32])
+{
+ unsigned int xzm1[64];
+ unsigned int xzm[64];
+ unsigned int xzmb[64];
+ unsigned int xzm1b[64];
+ unsigned int xznb[64];
+ unsigned int xzn1b[64];
+ unsigned int a0[64];
+ unsigned int a1[64];
+ unsigned int b0[64];
+ unsigned int b1[64];
+ unsigned int c1[64];
+ unsigned int r[32];
+ unsigned int s[32];
+ unsigned int t[32];
+ unsigned int u[32];
+ unsigned int j;
+ unsigned int b;
+ int pos;
+
+ for (j = 0;j < 32;++j) xzm1[j] = work[j];
+ xzm1[32] = 1;
+ for (j = 33;j < 64;++j) xzm1[j] = 0;
+
+ xzm[0] = 1;
+ for (j = 1;j < 64;++j) xzm[j] = 0;
+
+ for (pos = 254;pos >= 0;--pos) {
+ b = e[pos / 8] >> (pos & 7);
+ b &= 1;
+ select(xzmb,xzm1b,xzm,xzm1,b);
+ add(a0,xzmb,xzmb + 32);
+ sub(a0 + 32,xzmb,xzmb + 32);
+ add(a1,xzm1b,xzm1b + 32);
+ sub(a1 + 32,xzm1b,xzm1b + 32);
+ square(b0,a0);
+ square(b0 + 32,a0 + 32);
+ mult(b1,a1,a0 + 32);
+ mult(b1 + 32,a1 + 32,a0);
+ add(c1,b1,b1 + 32);
+ sub(c1 + 32,b1,b1 + 32);
+ square(r,c1 + 32);
+ sub(s,b0,b0 + 32);
+ mult121665(t,s);
+ add(u,t,b0);
+ mult(xznb,b0,b0 + 32);
+ mult(xznb + 32,s,u);
+ square(xzn1b,c1);
+ mult(xzn1b + 32,r,work);
+ select(xzm,xzm1,xznb,xzn1b,b);
+ }
+
+ for (j = 0;j < 64;++j) work[j] = xzm[j];
+}
+
+static void recip(unsigned int out[32],const unsigned int z[32])
+{
+ unsigned int z2[32];
+ unsigned int z9[32];
+ unsigned int z11[32];
+ unsigned int z2_5_0[32];
+ unsigned int z2_10_0[32];
+ unsigned int z2_20_0[32];
+ unsigned int z2_50_0[32];
+ unsigned int z2_100_0[32];
+ unsigned int t0[32];
+ unsigned int t1[32];
+ int i;
+
+ /* 2 */ square(z2,z);
+ /* 4 */ square(t1,z2);
+ /* 8 */ square(t0,t1);
+ /* 9 */ mult(z9,t0,z);
+ /* 11 */ mult(z11,z9,z2);
+ /* 22 */ square(t0,z11);
+ /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9);
+
+ /* 2^6 - 2^1 */ square(t0,z2_5_0);
+ /* 2^7 - 2^2 */ square(t1,t0);
+ /* 2^8 - 2^3 */ square(t0,t1);
+ /* 2^9 - 2^4 */ square(t1,t0);
+ /* 2^10 - 2^5 */ square(t0,t1);
+ /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0);
+
+ /* 2^11 - 2^1 */ square(t0,z2_10_0);
+ /* 2^12 - 2^2 */ square(t1,t0);
+ /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); }
+ /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0);
+
+ /* 2^21 - 2^1 */ square(t0,z2_20_0);
+ /* 2^22 - 2^2 */ square(t1,t0);
+ /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); }
+ /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0);
+
+ /* 2^41 - 2^1 */ square(t1,t0);
+ /* 2^42 - 2^2 */ square(t0,t1);
+ /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); }
+ /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0);
+
+ /* 2^51 - 2^1 */ square(t0,z2_50_0);
+ /* 2^52 - 2^2 */ square(t1,t0);
+ /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); }
+ /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0);
+
+ /* 2^101 - 2^1 */ square(t1,z2_100_0);
+ /* 2^102 - 2^2 */ square(t0,t1);
+ /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); }
+ /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0);
+
+ /* 2^201 - 2^1 */ square(t0,t1);
+ /* 2^202 - 2^2 */ square(t1,t0);
+ /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); }
+ /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0);
+
+ /* 2^251 - 2^1 */ square(t1,t0);
+ /* 2^252 - 2^2 */ square(t0,t1);
+ /* 2^253 - 2^3 */ square(t1,t0);
+ /* 2^254 - 2^4 */ square(t0,t1);
+ /* 2^255 - 2^5 */ square(t1,t0);
+ /* 2^255 - 21 */ mult(out,t1,z11);
+}
+
+static void crypto_scalarmult(unsigned char *q,
+ const unsigned char *n,
+ const unsigned char *p)
+{
+ unsigned int work[96];
+ unsigned char e[32];
+ unsigned int i;
+ for (i = 0;i < 32;++i) e[i] = n[i];
+ e[0] &= 248;
+ e[31] &= 127;
+ e[31] |= 64;
+ for (i = 0;i < 32;++i) work[i] = p[i];
+ mainloop(work,e);
+ recip(work + 32,work + 32);
+ mult(work + 64,work,work + 32);
+ freeze(work + 64);
+ for (i = 0;i < 32;++i) q[i] = work[64 + i];
+}
+
+void cf_curve25519_mul(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32])
+{
+ crypto_scalarmult(out, scalar, point);
+}
+
+void cf_curve25519_mul_base(uint8_t out[32], const uint8_t scalar[32])
+{
+ uint8_t base_point[32] = { 9 };
+ cf_curve25519_mul(out, scalar, base_point);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c
new file mode 100644
index 00000000..c98c1078
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/curve25519.tweetnacl.c
@@ -0,0 +1,235 @@
+/* This is based on tweetnacl. Some typedefs have been
+ * replaced with their stdint equivalents.
+ *
+ * Original code was public domain. */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "handy.h"
+
+typedef int64_t gf[16];
+
+static const uint8_t _0[16],
+ _9[32] = {9};
+static const gf gf0,
+ gf1 = {1},
+ _121665 = {0xDB41, 1},
+ D = {0x78a3, 0x1359, 0x4dca, 0x75eb,
+ 0xd8ab, 0x4141, 0x0a4d, 0x0070,
+ 0xe898, 0x7779, 0x4079, 0x8cc7,
+ 0xfe73, 0x2b6f, 0x6cee, 0x5203},
+ D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6,
+ 0xb156, 0x8283, 0x149a, 0x00e0,
+ 0xd130, 0xeef3, 0x80f2, 0x198e,
+ 0xfce7, 0x56df, 0xd9dc, 0x2406},
+ X = {0xd51a, 0x8f25, 0x2d60, 0xc956,
+ 0xa7b2, 0x9525, 0xc760, 0x692c,
+ 0xdc5c, 0xfdd6, 0xe231, 0xc0a4,
+ 0x53fe, 0xcd6e, 0x36d3, 0x2169},
+ Y = {0x6658, 0x6666, 0x6666, 0x6666,
+ 0x6666, 0x6666, 0x6666, 0x6666,
+ 0x6666, 0x6666, 0x6666, 0x6666,
+ 0x6666, 0x6666, 0x6666, 0x6666},
+ I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee,
+ 0xe478, 0xad2f, 0x1806, 0x2f43,
+ 0xd7a7, 0x3dfb, 0x0099, 0x2b4d,
+ 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
+
+static void set25519(gf r, const gf a)
+{
+ size_t i;
+ for (i = 0; i < 16; i++)
+ r[i] = a[i];
+}
+
+static void car25519(gf o)
+{
+ int64_t c;
+ size_t i;
+
+ for (i = 0; i < 16; i++)
+ {
+ o[i] += (1LL << 16);
+ c = o[i] >> 16;
+ o[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15);
+ o[i] -= c << 16;
+ }
+}
+
+static void sel25519(gf p, gf q, int64_t b)
+{
+ int64_t tmp, mask = ~(b-1);
+ size_t i;
+ for (i = 0; i < 16; i++)
+ {
+ tmp = mask & (p[i] ^ q[i]);
+ p[i] ^= tmp;
+ q[i] ^= tmp;
+ }
+}
+
+static void pack25519(uint8_t out[32], const gf n)
+{
+ size_t i, j;
+ int b;
+ gf m, t;
+ set25519(t, n);
+ car25519(t);
+ car25519(t);
+ car25519(t);
+
+ for(j = 0; j < 2; j++)
+ {
+ m[0] = t[0] - 0xffed;
+ for (i = 1; i < 15; i++)
+ {
+ m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
+ m[i - 1] &= 0xffff;
+ }
+ m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
+ b = (m[15] >> 16) & 1;
+ m[14] &= 0xffff;
+ sel25519(t, m, 1 - b);
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ out[2 * i] = t[i] & 0xff;
+ out[2 * i + 1] = (uint8_t) (t[i] >> 8);
+ }
+}
+
+
+
+static void unpack25519(gf o, const uint8_t *n)
+{
+ size_t i;
+ for (i = 0; i < 16; i++)
+ o[i] = n[2 * i] + ((int64_t) n[2 * i + 1] << 8);
+ o[15] &= 0x7fff;
+}
+
+static void add(gf o, const gf a, const gf b)
+{
+ size_t i;
+ for (i = 0; i < 16; i++)
+ o[i] = a[i] + b[i];
+}
+
+static void sub(gf o, const gf a, const gf b)
+{
+ size_t i;
+ for (i = 0; i < 16; i++)
+ o[i] = a[i] - b[i];
+}
+
+static void mul(gf o, const gf a, const gf b)
+{
+ int64_t t[31];
+ size_t i, j;
+
+ for (i = 0; i < 31; i++)
+ t[i] = 0;
+
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 16; j++)
+ t[i + j] += a[i] * b[j];
+
+ for (i = 0; i < 15; i++)
+ t[i] += 38 * t[i + 16];
+
+ for (i = 0; i < 16; i++)
+ o[i] = t[i];
+
+ car25519(o);
+ car25519(o);
+}
+
+static void sqr(gf o, const gf a)
+{
+ mul(o, a, a);
+}
+
+static void inv25519(gf o, const gf i)
+{
+ gf c;
+ int a;
+ for (a = 0; a < 16; a++)
+ c[a] = i[a];
+
+ for (a = 253; a >= 0; a--)
+ {
+ sqr(c, c);
+ if(a != 2 && a != 4)
+ mul(c, c, i);
+ }
+
+ for (a = 0; a < 16; a++)
+ o[a] = c[a];
+}
+
+
+void cf_curve25519_mul(uint8_t *q, const uint8_t *n, const uint8_t *p)
+{
+ uint8_t z[32];
+ gf x;
+ gf a, b, c, d, e, f;
+
+ {
+ size_t i;
+ for (i = 0; i < 31; i++)
+ z[i] = n[i];
+ z[31] = (n[31] & 127) | 64;
+ z[0] &= 248;
+
+ unpack25519(x, p);
+
+ for(i = 0; i < 16; i++)
+ {
+ b[i] = x[i];
+ d[i] = a[i] = c[i] = 0;
+ }
+ }
+
+ a[0] = d[0] = 1;
+
+ {int i;
+ for (i = 254; i >= 0; i--)
+ {
+ int64_t r = (z[i >> 3] >> (i & 7)) & 1;
+ sel25519(a, b, r);
+ sel25519(c, d, r);
+ add(e, a, c);
+ sub(a, a, c);
+ add(c, b, d);
+ sub(b, b, d);
+ sqr(d, e);
+ sqr(f, a);
+ mul(a, c, a);
+ mul(c, b, e);
+ add(e, a, c);
+ sub(a, a, c);
+ sqr(b, a);
+ sub(c, d, f);
+ mul(a, c, _121665);
+ add(a, a, d);
+ mul(c, c, a);
+ mul(a, d, f);
+ mul(d, b, x);
+ sqr(b, e);
+ sel25519(a, b, r);
+ sel25519(c, d, r);
+ }
+ }
+
+ inv25519(c, c);
+ mul(a, a, c);
+ pack25519(q, a);
+}
+
+void cf_curve25519_mul_base(uint8_t *q, const uint8_t *n)
+{
+ cf_curve25519_mul(q, n, _9);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.c
new file mode 100644
index 00000000..ae790678
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.c
@@ -0,0 +1,434 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "drbg.h"
+#include "handy.h"
+#include "bitops.h"
+#include "sha2.h"
+#include "tassert.h"
+
+#include <string.h>
+
+#define MAX_DRBG_GENERATE 0x10000ul
+
+static void hash_df(const cf_chash *H,
+ const void *in1, size_t nin1,
+ const void *in2, size_t nin2,
+ const void *in3, size_t nin3,
+ const void *in4, size_t nin4,
+ uint8_t *out, size_t nout)
+{
+ uint8_t counter = 1;
+ uint32_t bits_to_return = nout * 8;
+ uint8_t cbuf[4];
+ uint8_t block[CF_MAXHASH];
+
+ write32_be(bits_to_return, cbuf);
+
+ while (nout)
+ {
+ /* Make a block. This is the hash of:
+ * counter || bits_to_return || in1 || in2 || in3 | in4
+ */
+ cf_chash_ctx ctx;
+ H->init(&ctx);
+ H->update(&ctx, &counter, sizeof counter);
+ H->update(&ctx, cbuf, sizeof cbuf);
+ H->update(&ctx, in1, nin1);
+ H->update(&ctx, in2, nin2);
+ H->update(&ctx, in3, nin3);
+ H->update(&ctx, in4, nin4);
+ H->digest(&ctx, block);
+
+ size_t take = MIN(H->hashsz, nout);
+ memcpy(out, block, take);
+ out += take;
+ nout -= take;
+
+ counter += 1;
+ }
+}
+
+void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx,
+ const void *entropy, size_t nentropy,
+ const void *nonce, size_t nnonce,
+ const void *persn, size_t npersn)
+{
+ mem_clean(ctx, sizeof *ctx);
+
+ /* 1. seed_material = entropy_input || nonce || personalization_string
+ * 2. seed = Hash_df(seed_material, seedlen)
+ * 3. V = seed */
+ hash_df(&cf_sha256,
+ entropy, nentropy,
+ nonce, nnonce,
+ persn, npersn,
+ NULL, 0,
+ ctx->V, sizeof ctx->V);
+
+ /* 4. C = Hash_df(0x00 || V, seedlen) */
+ uint8_t zero = 0;
+ hash_df(&cf_sha256,
+ &zero, sizeof zero,
+ ctx->V, sizeof ctx->V,
+ NULL, 0,
+ NULL, 0,
+ ctx->C, sizeof ctx->C);
+
+ /* 5. reseed_counter = 1 */
+ ctx->reseed_counter = 1;
+}
+
+/* Add out += in, mod 2^nout.
+ * Runs in time dependent on nout and nin, but not the contents of out or in.
+ */
+static void add(uint8_t *out, size_t nout, const uint8_t *in, size_t nin)
+{
+ assert(nout >= nin);
+
+ uint16_t carry = 0;
+ int oi, ii;
+
+ for (oi = nout - 1, ii = nin - 1;
+ oi >= 0;
+ ii--, oi--)
+ {
+ carry += out[oi];
+ if (ii >= 0)
+ carry += in[ii];
+ out[oi] = carry & 0xff;
+ carry >>= 8;
+ }
+}
+
+static void hash_process_addnl(const cf_chash *H,
+ const void *input, size_t ninput,
+ uint8_t *V, size_t nV)
+{
+ if (!ninput)
+ return;
+
+ /* 2.1. w = Hash(0x02 || V || additional_input) */
+ uint8_t two = 2;
+ uint8_t w[CF_MAXHASH];
+ cf_chash_ctx ctx;
+ H->init(&ctx);
+ H->update(&ctx, &two, sizeof two);
+ H->update(&ctx, V, nV);
+ H->update(&ctx, input, ninput);
+ H->digest(&ctx, w);
+
+ /* 2.2. V = (V + w) mod 2 ^ seedlen */
+ add(V, nV, w, H->hashsz);
+}
+
+static void hash_generate(const cf_chash *H,
+ uint8_t *data, size_t ndata, /* initialised with V */
+ void *out, size_t nout)
+{
+ cf_chash_ctx ctx;
+ uint8_t w[CF_MAXHASH];
+ uint8_t *bout = out;
+ uint8_t one = 1;
+
+ while (nout)
+ {
+ /* 4.1. w = Hash(data) */
+ H->init(&ctx);
+ H->update(&ctx, data, ndata);
+ H->digest(&ctx, w);
+
+ /* 4.2. W = W || w */
+ size_t take = MIN(H->hashsz, nout);
+ memcpy(bout, w, take);
+ bout += take;
+ nout -= take;
+
+ /* 4.3. data = (data + 1) mod 2 ^ seedlen */
+ add(data, ndata, &one, sizeof one);
+ }
+}
+
+static void hash_step(const cf_chash *H,
+ uint8_t *V, size_t nV,
+ const uint8_t *C, size_t nC,
+ uint32_t *reseed_counter)
+{
+ /* 4. h = Hash(0x03 || V) */
+ uint8_t h[CF_MAXHASH];
+ uint8_t three = 3;
+ cf_chash_ctx ctx;
+
+ H->init(&ctx);
+ H->update(&ctx, &three, sizeof three);
+ H->update(&ctx, V, nV);
+ H->digest(&ctx, h);
+
+ /* 5. V = (V + h + C + reseed_counter) mod 2 ^ seedlen */
+ uint8_t reseed_counter_buf[4];
+ write32_be(*reseed_counter, reseed_counter_buf);
+
+ add(V, nV, h, H->hashsz);
+ add(V, nV, C, nC);
+ add(V, nV, reseed_counter_buf, sizeof reseed_counter_buf);
+
+ /* 6. reseed_counter = reseed_counter + 1 */
+ *reseed_counter = *reseed_counter + 1;
+}
+
+/* This is Hash_DRBG_Generate_algorithm.
+ * nout is a maximum of MAX_DRBG_GENERATE */
+static void hash_gen_request(cf_hash_drbg_sha256 *ctx,
+ const void *addnl, size_t naddnl,
+ void *out, size_t nout)
+{
+ uint8_t data[440/8]; /* a temporary copy of V, which gets incremented by generate */
+
+ assert(!cf_hash_drbg_sha256_needs_reseed(ctx));
+
+ hash_process_addnl(&cf_sha256, addnl, naddnl, ctx->V, sizeof ctx->V);
+ assert(sizeof data == sizeof ctx->V);
+ memcpy(data, ctx->V, sizeof ctx->V);
+ hash_generate(&cf_sha256, data, sizeof data, out, nout);
+ hash_step(&cf_sha256, ctx->V, sizeof ctx->V, ctx->C, sizeof ctx->C, &ctx->reseed_counter);
+}
+
+void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx,
+ const void *addnl, size_t naddnl,
+ void *out, size_t nout)
+{
+ uint8_t *bout = out;
+
+ /* Generate output in requests of MAX_DRBG_GENERATE in size. */
+ while (nout != 0)
+ {
+ size_t take = MIN(MAX_DRBG_GENERATE, nout);
+ hash_gen_request(ctx, addnl, naddnl, bout, take);
+ bout += take;
+ nout -= take;
+
+ /* Add additional data only once. */
+ addnl = NULL;
+ naddnl = 0;
+ }
+}
+
+void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx,
+ void *out, size_t nout)
+{
+ cf_hash_drbg_sha256_gen_additional(ctx,
+ NULL, 0,
+ out, nout);
+}
+
+void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx,
+ const void *entropy, size_t nentropy,
+ const void *addnl, size_t naddnl)
+{
+ /* 1. seed_material = 0x01 || V || entropy_input || additional_input
+ * 2. seed = Hash_df(seed_material, seedlen)
+ * 3. V = seed */
+ uint8_t one = 1;
+ /* stash V in C, because it cannot alias output */
+ memcpy(ctx->C, ctx->V, sizeof ctx->C);
+ hash_df(&cf_sha256,
+ &one, sizeof one,
+ ctx->C, sizeof ctx->C,
+ entropy, nentropy,
+ addnl, naddnl,
+ ctx->V, sizeof ctx->V);
+
+ /* 4. C = Hash_df(0x00 || V, seedlen) */
+ uint8_t zero = 0;
+ hash_df(&cf_sha256,
+ &zero, sizeof zero,
+ ctx->V, sizeof ctx->V,
+ NULL, 0,
+ NULL, 0,
+ ctx->C, sizeof ctx->C);
+
+ /* 5. reseed_counter = 1 */
+ ctx->reseed_counter = 1;
+}
+
+uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx)
+{
+ /* we need reseeding after 2 ^ 32 - 1 requests. */
+ return ctx->reseed_counter == 0;
+}
+
+/* --- HMAC_DRBG --- */
+
+/* provided_data is in1 || in2 || in3.
+ * K is already scheduled in ctx->hmac. */
+static void hmac_drbg_update(cf_hmac_drbg *ctx,
+ const void *in1, size_t nin1,
+ const void *in2, size_t nin2,
+ const void *in3, size_t nin3)
+{
+ cf_hmac_ctx local;
+ const cf_chash *H = ctx->hmac.hash;
+ uint8_t new_key[CF_MAXHASH];
+ uint8_t zero = 0;
+
+ /* 1. K = HMAC(K, V || 0x00 || provided_data) */
+ local = ctx->hmac;
+ cf_hmac_update(&local, ctx->V, H->hashsz);
+ cf_hmac_update(&local, &zero, sizeof zero);
+ cf_hmac_update(&local, in1, nin1);
+ cf_hmac_update(&local, in2, nin2);
+ cf_hmac_update(&local, in3, nin3);
+ cf_hmac_finish(&local, new_key);
+ cf_hmac_init(&ctx->hmac, H, new_key, H->hashsz);
+ mem_clean(new_key, sizeof new_key);
+
+ /* 2. V = HMAC(K, V) */
+ local = ctx->hmac;
+ cf_hmac_update(&local, ctx->V, H->hashsz);
+ cf_hmac_finish(&local, ctx->V);
+
+ /* 3. if (provided_data = null) then return K and V */
+ if (nin1 == 0 && nin2 == 0 && nin3 == 0)
+ return;
+
+ /* 4. K = HMAC(K, V || 0x01 || provided_data) */
+ uint8_t one = 1;
+ local = ctx->hmac;
+ cf_hmac_update(&local, ctx->V, H->hashsz);
+ cf_hmac_update(&local, &one, sizeof one);
+ cf_hmac_update(&local, in1, nin1);
+ cf_hmac_update(&local, in2, nin2);
+ cf_hmac_update(&local, in3, nin3);
+ cf_hmac_finish(&local, new_key);
+ cf_hmac_init(&ctx->hmac, H, new_key, H->hashsz);
+ mem_clean(new_key, sizeof new_key);
+
+ /* 5. V = HMAC(K, V) */
+ local = ctx->hmac;
+ cf_hmac_update(&local, ctx->V, H->hashsz);
+ cf_hmac_finish(&local, ctx->V);
+}
+
+void cf_hmac_drbg_init(cf_hmac_drbg *ctx,
+ const cf_chash *hash,
+ const void *entropy, size_t nentropy,
+ const void *nonce, size_t nnonce,
+ const void *persn, size_t npersn)
+{
+ mem_clean(ctx, sizeof *ctx);
+
+ assert(hash->hashsz <= CF_MAXHASH);
+
+ /* 2. Key = 0x00 00 ... 00
+ * 3. V = 0x01 01 ... 01 */
+ uint8_t initial_key[CF_MAXHASH];
+ memset(initial_key, 0x00, hash->hashsz);
+ memset(ctx->V, 0x01, hash->hashsz);
+ cf_hmac_init(&ctx->hmac, hash, initial_key, hash->hashsz);
+
+ /* 1. seed_material = entropy_input || nonce || personalization_string
+ * 4. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V) */
+ hmac_drbg_update(ctx, entropy, nentropy, nonce, nnonce, persn, npersn);
+
+ /* 5. reseed_counter = 1 */
+ ctx->reseed_counter = 1;
+}
+
+uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx)
+{
+ return ctx->reseed_counter == 0;
+}
+
+static void hmac_drbg_generate(cf_hmac_drbg *ctx,
+ const void *addnl, size_t naddnl,
+ void *out, size_t nout)
+{
+ /* 1. If reseed_counter > reseed_interval, then return an indication
+ * that a reseed is required */
+ assert(!cf_hmac_drbg_needs_reseed(ctx));
+
+ /* 2. If additional_input != null, then
+ * (Key, V) = HMAC_DRBG_Update(additional_input, Key, V)
+ */
+ if (naddnl)
+ hmac_drbg_update(ctx, addnl, naddnl, NULL, 0, NULL, 0);
+
+ /* 3. temp = Null
+ * 4. While (len(temp) < requested_number_of_bits) do:
+ * 4.1. V = HMAC(Key, V)
+ * 4.2. temp = temp || V
+ * 5. returned_bits = leftmost(temp, requested_number_of_bits)
+ *
+ * We write the contents of temp directly into the caller's
+ * out buffer.
+ */
+ uint8_t *bout = out;
+ cf_hmac_ctx local;
+
+ while (nout)
+ {
+ local = ctx->hmac;
+ cf_hmac_update(&local, ctx->V, ctx->hmac.hash->hashsz);
+ cf_hmac_finish(&local, ctx->V);
+
+ size_t take = MIN(ctx->hmac.hash->hashsz, nout);
+ memcpy(bout, ctx->V, take);
+ bout += take;
+ nout -= take;
+ }
+
+ /* 6. (Key, V) = HMAC_DRBG_Update(additional_input, Key, V) */
+ hmac_drbg_update(ctx, addnl, naddnl, NULL, 0, NULL, 0);
+
+ /* 7. reseed_counter = reseed_counter + 1 */
+ ctx->reseed_counter++;
+}
+
+void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx,
+ const void *addnl, size_t naddnl,
+ void *out, size_t nout)
+{
+ uint8_t *bout = out;
+
+ while (nout != 0)
+ {
+ size_t take = MIN(MAX_DRBG_GENERATE, nout);
+ hmac_drbg_generate(ctx, addnl, naddnl, bout, take);
+ bout += take;
+ nout -= take;
+
+ /* Add additional data only once. */
+ addnl = NULL;
+ naddnl = 0;
+ }
+}
+
+void cf_hmac_drbg_gen(cf_hmac_drbg *ctx, void *out, size_t nout)
+{
+ cf_hmac_drbg_gen_additional(ctx,
+ NULL, 0,
+ out, nout);
+}
+
+void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx,
+ const void *entropy, size_t nentropy,
+ const void *addnl, size_t naddnl)
+{
+ /* 1. seed_material = entropy_input || additional_input
+ * 2. (Key, V) = HMAC_DRBG_Update(seed_material, Key, V) */
+ hmac_drbg_update(ctx, entropy, nentropy, addnl, naddnl, NULL, 0);
+
+ /* 3. reseed_counter = 1 */
+ ctx->reseed_counter = 1;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.h
new file mode 100644
index 00000000..18a10704
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/drbg.h
@@ -0,0 +1,191 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "chash.h"
+#include "hmac.h"
+
+/**
+ * Hash_DRBG
+ * =========
+ * This is Hash_DRBG from SP800-90A rev 1, with SHA256 as
+ * the underlying hash function.
+ *
+ * This generator enforces a `reseed_interval` of 2^32-1:
+ * use :c:func:`cf_hash_drbg_sha256_needs_reseed` to check
+ * whether you need to reseed before use, and reseed using
+ * :c:func:`cf_hash_drbg_sha256_reseed`. If you try to use
+ * the generator when it thinks it needs reseeding, it will
+ * call `abort`.
+ *
+ * Internally it enforces a `max_number_of_bits_per_request`
+ * of 2^19 bits. It sorts out chunking up multiple requests
+ * for you though, so feel free to ask for more than 2^16 bytes
+ * at a time. If you provide additional input when doing that,
+ * it is added only once, on the first subrequest.
+ *
+ * It does not enforce any `max_length` or
+ * `max_personalization_string_length`.
+ */
+
+/* .. c:type:: cf_hash_drbg_sha256
+ * Hash_DRBG with SHA256 context.
+ *
+ * .. c:member:: cf_hash_drbg_sha256.V
+ * Current internal state.
+ *
+ * .. c:member:: cf_hash_drbg_sha256.C
+ * Current update offset.
+ *
+ * .. c:member:: cf_hash_drbg_sha256.reseed_counter
+ * Current number of times entropy has been extracted from
+ * generator.
+ */
+typedef struct
+{
+ uint8_t V[440/8];
+ uint8_t C[440/8];
+ uint32_t reseed_counter;
+} cf_hash_drbg_sha256;
+
+/* .. c:function:: $DECL
+ * Initialises the generator state `ctx`, using the provided `entropy`,
+ * `nonce` and personalisation string `persn`.
+ */
+extern void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx,
+ const void *entropy, size_t nentropy,
+ const void *nonce, size_t nnonce,
+ const void *persn, size_t npersn);
+
+/* .. c:function:: $DECL
+ * Returns non-zero if the generator needs reseeding. If
+ * this function returns non-zero, the next :c:func:`cf_hash_drbg_sha256_gen`
+ * or :c:func:`cf_hash_drbg_sha256_gen_additional` call will call `abort`.
+ */
+extern uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx);
+
+/* .. c:function:: $DECL
+ * Reseeds the generator with the given `entropy` and additional data `addnl`.
+ */
+extern void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx,
+ const void *entropy, size_t nentropy,
+ const void *addnl, size_t naddnl);
+
+/* .. c:function:: $DECL
+ * Generates pseudo-random output, writing `nout` bytes at `out`.
+ * This function aborts if the generator needs seeding.
+ */
+extern void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx,
+ void *out, size_t nout);
+
+/* .. c:function:: $DECL
+ * Generates pseudo-random output, writing `nout` bytes at `out`.
+ * At the same time, `addnl` is input to the generator as further
+ * entropy.
+ * This function aborts if the generator needs seeding.
+ */
+extern void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx,
+ const void *addnl, size_t naddnl,
+ void *out, size_t nout);
+
+/**
+ * HMAC_DRBG
+ * =========
+ * This is HMAC_DRBG from SP800-90a r1 with any hash function.
+ *
+ * This generator enforces a `reseed_interval` of 2^32-1:
+ * use :c:func:`cf_hmac_drbg_needs_reseed` to check whether
+ * you need to reseed before use, and reseed using
+ * :c:func:`cf_hmac_drbg_reseed`. If you try to use the
+ * generator when it thinks it needs reseeding, it will
+ * call `abort`.
+ *
+ * Internally it enforces a `max_number_of_bits_per_request`
+ * of 2^19 bits. It sorts out chunking up multiple requests
+ * for you though, so feel free to ask for more than 2^16 bytes
+ * at a time. If you provide additional input when doing that,
+ * it is added only once, on the first subrequest.
+ *
+ * It does not enforce any `max_length` or
+ * `max_personalization_string_length`.
+ */
+
+/* .. c:type:: cf_hmac_drbg
+ * HMAC_DRBG context.
+ *
+ * .. c:member:: cf_hmac_drbg.V
+ * Current internal state.
+ *
+ * .. c:member:: cf_hmac_drbg.hmac
+ * Current HMAC context, with key scheduled in it.
+ *
+ * .. c:member:: cf_hmac_drbg.reseed_counter
+ * Current number of times entropy has been extracted from
+ * generator.
+ */
+typedef struct
+{
+ uint8_t V[CF_MAXHASH];
+ cf_hmac_ctx hmac; /* pristine context with key scheduled */
+ uint32_t reseed_counter;
+} cf_hmac_drbg;
+
+/* .. c:function:: $DECL
+ * Initialises the generator state `ctx`, using the provided `entropy`,
+ * `nonce` and personalisation string `persn`.
+ */
+extern void cf_hmac_drbg_init(cf_hmac_drbg *ctx,
+ const cf_chash *hash,
+ const void *entropy, size_t nentropy,
+ const void *nonce, size_t nnonce,
+ const void *persn, size_t npersn);
+
+/* .. c:function:: $DECL
+ * Returns non-zero if the generator needs reseeding. If
+ * this function returns non-zero, the next :c:func:`cf_hmac_drbg_gen`
+ * or :c:func:`cf_hmac_drbg_gen_additional` call will call `abort`.
+ */
+extern uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx);
+
+/* .. c:function:: $DECL
+ * Reseeds the generator with the given `entropy` and additional data
+ * `addnl`.
+ */
+extern void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx,
+ const void *entropy, size_t nentropy,
+ const void *addnl, size_t naddnl);
+
+/* .. c:function:: $DECL
+ * Generates pseudo-random output, writing `nout` bytes at `out`.
+ * This function aborts if the generator needs seeding.
+ */
+extern void cf_hmac_drbg_gen(cf_hmac_drbg *ctx,
+ void *out, size_t nout);
+
+/* .. c:function:: $DECL
+ * Generates pseudo-random output, writing `nout` bytes at `out`.
+ * At the same time, `addnl` is input to the generator as further
+ * entropy.
+ * This function aborts if the generator needs seeding.
+ */
+extern void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx,
+ const void *addnl, size_t naddnl,
+ void *out, size_t nout);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/eax.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/eax.c
new file mode 100644
index 00000000..80ba46f4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/eax.c
@@ -0,0 +1,116 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "tassert.h"
+
+#include <string.h>
+
+static void cmac_compute_n(cf_cmac_stream *ctx,
+ uint8_t t,
+ const uint8_t *input, size_t ninput,
+ uint8_t out[CF_MAXBLOCK])
+{
+ size_t blocksz = ctx->cmac.prp->blocksz;
+ assert(blocksz > 0);
+
+ uint8_t firstblock[CF_MAXBLOCK];
+ memset(firstblock, 0, blocksz);
+ firstblock[blocksz - 1] = t;
+
+ cf_cmac_stream_reset(ctx);
+ if (ninput)
+ {
+ cf_cmac_stream_update(ctx, firstblock, blocksz, 0);
+ cf_cmac_stream_update(ctx, input, ninput, 1);
+ } else {
+ cf_cmac_stream_update(ctx, firstblock, blocksz, 1);
+ }
+
+ cf_cmac_stream_final(ctx, out);
+}
+
+void cf_eax_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher, /* the same size as nplain */
+ uint8_t *tag, size_t ntag)
+{
+ uint8_t NN[CF_MAXBLOCK],
+ HH[CF_MAXBLOCK],
+ CC[CF_MAXBLOCK];
+
+ cf_cmac_stream cmac;
+ cf_cmac_stream_init(&cmac, prp, prpctx);
+
+ /* NN = OMAC_K^0(N) */
+ cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
+
+ /* HH = OMAC_K^1(H) */
+ cmac_compute_n(&cmac, 1, header, nheader, HH);
+
+ /* C = CTR_K^NN(M) */
+ cf_ctr ctr;
+ cf_ctr_init(&ctr, prp, prpctx, NN);
+ cf_ctr_cipher(&ctr, plain, cipher, nplain);
+
+ /* CC = OMAC_K^2(C) */
+ cmac_compute_n(&cmac, 2, cipher, nplain, CC);
+
+ /* Tag = NN ^ CC ^ HH
+ * T = Tag [ first tau bits ] */
+ assert(ntag <= prp->blocksz);
+ for (size_t i = 0; i < ntag; i++)
+ tag[i] = NN[i] ^ CC[i] ^ HH[i];
+}
+
+int cf_eax_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain) /* the same size as ncipher */
+{
+ uint8_t NN[CF_MAXBLOCK],
+ HH[CF_MAXBLOCK],
+ CC[CF_MAXBLOCK];
+
+ cf_cmac_stream cmac;
+ cf_cmac_stream_init(&cmac, prp, prpctx);
+
+ /* NN = OMAC_K^0(N) */
+ cmac_compute_n(&cmac, 0, nonce, nnonce, NN);
+
+ /* HH = OMAC_K^1(H) */
+ cmac_compute_n(&cmac, 1, header, nheader, HH);
+
+ /* CC = OMAC_K^2(C) */
+ cmac_compute_n(&cmac, 2, cipher, ncipher, CC);
+
+ uint8_t tt[CF_MAXBLOCK];
+ assert(ntag && ntag <= prp->blocksz);
+ for (size_t i = 0; i < ntag; i++)
+ tt[i] = NN[i] ^ CC[i] ^ HH[i];
+
+ if (!mem_eq(tt, tag, ntag))
+ return 1;
+
+ cf_ctr ctr;
+ cf_ctr_init(&ctr, prp, prpctx, NN);
+ cf_ctr_cipher(&ctr, cipher, plain, ncipher);
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/cutest.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/cutest.h
new file mode 100644
index 00000000..c9af425e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/cutest.h
@@ -0,0 +1,620 @@
+/*
+ * CUTest -- C/C++ Unit Test facility
+ * <http://github.com/mity/cutest>
+ *
+ * Copyright (c) 2013-2014 Martin Mitas
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef CUTEST_H__
+#define CUTEST_H__
+
+
+/************************
+ *** Public interface ***
+ ************************/
+
+/* By default, <cutest.h> provides the main program entry point (function
+ * main()). However, if the test suite is composed of multiple source files
+ * which include <cutest.h>, then this brings a problem of multiple main()
+ * definitions. To avoid this problem, #define macro TEST_NO_MAIN in all
+ * compilation units but one.
+ */
+
+/* Macro to specify list of unit tests in the suite.
+ * The unit test implementation MUST provide list of unit tests it implements
+ * with this macro:
+ *
+ * TEST_LIST = {
+ * { "test1_name", test1_func_ptr },
+ * { "test2_name", test2_func_ptr },
+ * ...
+ * { 0 }
+ * };
+ *
+ * The list specifies names of each tests (must be unique) and pointer to
+ * a function implementing it. The function does not take any arguments
+ * and have no return values, i.e. the test functions should have this
+ * prototype:
+ *
+ * void test_func(void);
+ */
+#define TEST_LIST const struct test__ test_list__[]
+
+
+/* Macros for testing whether an unit test succeeds or fails. These macros
+ * can be used arbitrarily in functions implementing the unit tests.
+ *
+ * If any condition fails throughout execution of a test, the test fails.
+ *
+ * TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows
+ * also to specify an error message to print out if the condition fails.
+ * (It expects printf-like format string and its parameters). The macros
+ * return non-zero (condition passes) or 0 (condition fails).
+ *
+ * That can be useful when more conditions should be checked only if some
+ * preceding condition passes, as illustrated here:
+ *
+ * SomeStruct* ptr = allocate_some_struct();
+ * if(TEST_CHECK(ptr != NULL)) {
+ * TEST_CHECK(ptr->member1 < 100);
+ * TEST_CHECK(ptr->member2 > 200);
+ * }
+ */
+#define TEST_CHECK_(cond,...) test_check__((cond), __FILE__, __LINE__, __VA_ARGS__)
+#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, "%s", #cond)
+
+
+/**********************
+ *** Implementation ***
+ **********************/
+
+/* The unit test files should not rely on anything below. */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)
+ #define CUTEST_UNIX__ 1
+ #include <errno.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <signal.h>
+#endif
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+ #define CUTEST_WIN__ 1
+ #include <windows.h>
+ #include <io.h>
+#endif
+
+#ifdef __cplusplus
+ #include <exception>
+#endif
+
+
+/* Note our global private identifiers end with '__' to minimize risk of clash
+ * with the unit tests implementation. */
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+struct test__ {
+ const char* name;
+ void (*func)(void);
+};
+
+extern const struct test__ test_list__[];
+extern int test_verbose_level__;
+extern const struct test__* test_current_unit__;
+extern int test_current_already_logged__;
+extern int test_current_failures__;
+extern int test_colorize__;
+
+
+#define CUTEST_COLOR_DEFAULT__ 0
+#define CUTEST_COLOR_GREEN__ 1
+#define CUTEST_COLOR_RED__ 2
+#define CUTEST_COLOR_DEFAULT_INTENSIVE__ 3
+#define CUTEST_COLOR_GREEN_INTENSIVE__ 4
+#define CUTEST_COLOR_RED_INTENSIVE__ 5
+
+size_t
+test_print_in_color(int color, const char* fmt, ...)
+{
+ va_list args;
+ char buffer[256];
+ size_t n;
+
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ va_end(args);
+ buffer[sizeof(buffer)-1] = '\0';
+
+ if(!test_colorize__) {
+ return printf("%s", buffer);
+ }
+
+#if defined CUTEST_UNIX__
+ const char* col_str;
+ switch(color) {
+ case CUTEST_COLOR_GREEN__: col_str = "\e[0;32m"; break;
+ case CUTEST_COLOR_RED__: col_str = "\e[0;31m"; break;
+ case CUTEST_COLOR_GREEN_INTENSIVE__: col_str = "\e[1;32m"; break;
+ case CUTEST_COLOR_RED_INTENSIVE__: col_str = "\e[1;30m"; break;
+ case CUTEST_COLOR_DEFAULT_INTENSIVE__: col_str = "\e[1m"; break;
+ default: col_str = "\e[0m"; break;
+ }
+ printf("%s", col_str);
+ n = printf("%s", buffer);
+ printf("\e[0m");
+ return n;
+#elif defined CUTEST_WIN__
+ HANDLE h;
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ WORD attr;
+
+ h = GetStdHandle(STD_OUTPUT_HANDLE);
+ GetConsoleScreenBufferInfo(h, &info);
+
+ switch(color) {
+ case CUTEST_COLOR_GREEN__: attr = FOREGROUND_GREEN; break;
+ case CUTEST_COLOR_RED__: attr = FOREGROUND_RED; break;
+ case CUTEST_COLOR_GREEN_INTENSIVE__: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break;
+ case CUTEST_COLOR_RED_INTENSIVE__: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break;
+ case CUTEST_COLOR_DEFAULT_INTENSIVE__: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break;
+ default: attr = 0; break;
+ }
+ if(attr != 0)
+ SetConsoleTextAttribute(h, attr);
+ n = printf("%s", buffer);
+ SetConsoleTextAttribute(h, info.wAttributes);
+ return n;
+#else
+ n = printf("%s", buffer);
+ return n;
+#endif
+}
+
+int
+test_check__(int cond, const char* file, int line, const char* fmt, ...)
+{
+ const char *result_str;
+ int result_color;
+ int verbose_level;
+
+ if(cond) {
+ result_str = "ok";
+ result_color = CUTEST_COLOR_GREEN__;
+ verbose_level = 3;
+ } else {
+ if(!test_current_already_logged__ && test_current_unit__ != NULL) {
+ printf("[ ");
+ test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, "FAILED");
+ printf(" ]\n");
+ }
+ result_str = "failed";
+ result_color = CUTEST_COLOR_RED__;
+ verbose_level = 2;
+ test_current_failures__++;
+ test_current_already_logged__++;
+ }
+
+ if(test_verbose_level__ >= verbose_level) {
+ size_t n = 0;
+ va_list args;
+
+ printf(" ");
+
+ if(file != NULL)
+ n += printf("%s:%d: Check ", file, line);
+
+ va_start(args, fmt);
+ n += vprintf(fmt, args);
+ va_end(args);
+
+ printf("... ");
+ test_print_in_color(result_color, result_str);
+ printf("\n");
+ test_current_already_logged__++;
+ }
+
+ return (cond != 0);
+}
+
+
+#ifndef TEST_NO_MAIN
+
+static char* test_argv0__ = NULL;
+static int test_count__ = 0;
+static int test_no_exec__ = 0;
+static int test_no_summary__ = 0;
+static int test_skip_mode__ = 0;
+
+static int test_stat_failed_units__ = 0;
+static int test_stat_run_units__ = 0;
+
+const struct test__* test_current_unit__ = NULL;
+int test_current_already_logged__ = 0;
+int test_verbose_level__ = 2;
+int test_current_failures__ = 0;
+int test_colorize__ = 0;
+
+
+static void
+test_list_names__(void)
+{
+ const struct test__* test;
+
+ printf("Unit tests:\n");
+ for(test = &test_list__[0]; test->func != NULL; test++)
+ printf(" %s\n", test->name);
+}
+
+static const struct test__*
+test_by_name__(const char* name)
+{
+ const struct test__* test;
+
+ for(test = &test_list__[0]; test->func != NULL; test++) {
+ if(strcmp(test->name, name) == 0)
+ return test;
+ }
+
+ return NULL;
+}
+
+static int
+test_do_run__(const struct test__* test)
+{
+ test_current_unit__ = test;
+ test_current_failures__ = 0;
+ test_current_already_logged__ = 0;
+
+ if(test_verbose_level__ >= 3) {
+ test_print_in_color(CUTEST_COLOR_DEFAULT_INTENSIVE__, "Test %s:\n", test->name);
+ test_current_already_logged__++;
+ } else if(test_verbose_level__ >= 1) {
+ size_t n;
+ char spaces[32];
+
+ n = test_print_in_color(CUTEST_COLOR_DEFAULT_INTENSIVE__, "Test %s... ", test->name);
+ memset(spaces, ' ', sizeof(spaces));
+ if(n < sizeof(spaces))
+ printf("%.*s", (int) (sizeof(spaces) - n), spaces);
+ } else {
+ test_current_already_logged__ = 1;
+ }
+
+#ifdef __cplusplus
+ try {
+#endif
+
+ test->func();
+
+#ifdef __cplusplus
+ } catch(std::exception& e) {
+ const char* what = e.what();
+ if(what != NULL)
+ test_check__(0, NULL, 0, "Threw std::exception: %s", what);
+ else
+ test_check__(0, NULL, 0, "Threw std::exception");
+ } catch(...) {
+ test_check__(0, NULL, 0, "Threw an exception");
+ }
+#endif
+
+ if(test_verbose_level__ >= 3) {
+ switch(test_current_failures__) {
+ case 0: test_print_in_color(CUTEST_COLOR_GREEN_INTENSIVE__, " All conditions have passed.\n\n"); break;
+ case 1: test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, " One condition has FAILED.\n\n"); break;
+ default: test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, " %d conditions have FAILED.\n\n", test_current_failures__); break;
+ }
+ } else if(test_verbose_level__ >= 1 && test_current_failures__ == 0) {
+ printf("[ ");
+ test_print_in_color(CUTEST_COLOR_GREEN_INTENSIVE__, "OK");
+ printf(" ]\n");
+ }
+
+ test_current_unit__ = NULL;
+ return (test_current_failures__ == 0) ? 0 : -1;
+}
+
+static void
+test_error__(const char* fmt, ...)
+{
+ va_list args;
+
+ if(!test_current_already_logged__ && test_current_unit__ != NULL) {
+ printf("[ ");
+ test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, "FAILED");
+ printf(" ]\n");
+ }
+
+ if(test_verbose_level__ < 2)
+ return;
+
+ test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__, " Error: ");
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ printf("\n");
+}
+
+static void
+test_run__(const struct test__* test)
+{
+ int failed = 1;
+
+ test_current_unit__ = test;
+ test_current_already_logged__ = 0;
+
+ if(!test_no_exec__) {
+
+#if defined(CUTEST_UNIX__)
+
+ pid_t pid;
+ int exit_code;
+
+ pid = fork();
+ if(pid == (pid_t)-1) {
+ test_error__("Cannot fork. %s [%d]", strerror(errno), errno);
+ failed = 1;
+ } else if(pid == 0) {
+ failed = (test_do_run__(test) != 0);
+ exit(failed ? 1 : 0);
+ } else {
+ waitpid(pid, &exit_code, 0);
+ if(WIFEXITED(exit_code)) {
+ switch(WEXITSTATUS(exit_code)) {
+ case 0: failed = 0; break; /* test has passed. */
+ case 1: /* noop */ break; /* "normal" failure. */
+ default: test_error__("Unexpected exit code [%d]", WEXITSTATUS(exit_code));
+ }
+ } else if(WIFSIGNALED(exit_code)) {
+ char tmp[32];
+ const char* signame;
+ switch(WTERMSIG(exit_code)) {
+ case SIGINT: signame = "SIGINT"; break;
+ case SIGHUP: signame = "SIGHUP"; break;
+ case SIGQUIT: signame = "SIGQUIT"; break;
+ case SIGABRT: signame = "SIGABRT"; break;
+ case SIGKILL: signame = "SIGKILL"; break;
+ case SIGSEGV: signame = "SIGSEGV"; break;
+ case SIGILL: signame = "SIGILL"; break;
+ case SIGTERM: signame = "SIGTERM"; break;
+ default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break;
+ }
+ test_error__("Test interrupted by %s", signame);
+ } else {
+ test_error__("Test ended in an unexpected way [%d]", exit_code);
+ }
+ }
+
+#elif defined(CUTEST_WIN__)
+
+ char buffer[512] = {0};
+ STARTUPINFOA startupInfo = {0};
+ PROCESS_INFORMATION processInfo;
+ DWORD exitCode;
+
+ _snprintf(buffer, sizeof(buffer)-1,
+ "%s --no-exec --no-summary --verbose=%d --color=%s -- \"%s\"",
+ test_argv0__, test_verbose_level__,
+ test_colorize__ ? "always" : "never", test->name);
+ startupInfo.cb = sizeof(STARTUPINFO);
+ if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) {
+ WaitForSingleObject(processInfo.hProcess, INFINITE);
+ GetExitCodeProcess(processInfo.hProcess, &exitCode);
+ CloseHandle(processInfo.hThread);
+ CloseHandle(processInfo.hProcess);
+ failed = (exitCode != 0);
+ } else {
+ test_error__("Cannot create unit test subprocess [%ld].", GetLastError());
+ failed = 1;
+ }
+
+#else
+
+ failed = (test_do_run__(test) != 0);
+
+#endif
+
+ } else {
+ failed = (test_do_run__(test) != 0);
+ }
+
+ test_current_unit__ = NULL;
+
+ test_stat_run_units__++;
+ if(failed)
+ test_stat_failed_units__++;
+}
+
+#if defined(CUTEST_WIN__)
+static LONG CALLBACK
+test_exception_filter__(EXCEPTION_POINTERS *ptrs)
+{
+ test_error__("Unhandled SEH exception %08lx at %p.",
+ ptrs->ExceptionRecord->ExceptionCode,
+ ptrs->ExceptionRecord->ExceptionAddress);
+ fflush(stdout);
+ fflush(stderr);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif
+
+static void
+test_help__(void)
+{
+ printf("Usage: %s [options] [test...]\n", test_argv0__);
+ printf("Run the specified unit tests; or if the option '--skip' is used, run all\n");
+ printf("tests in the suite but those listed. By default, if no tests are specified\n");
+ printf("on the command line, all unit tests in the suite are run.\n");
+ printf("\n");
+ printf("Options:\n");
+ printf(" -s, --skip Execute all unit tests but the listed ones\n");
+ printf(" --no-exec Do not execute unit tests as child processes\n");
+ printf(" --no-summary Suppress printing of test results summary\n");
+ printf(" -l, --list List unit tests in the suite and exit\n");
+ printf(" -v, --verbose Enable more verbose output\n");
+ printf(" --verbose=LEVEL Set verbose level to LEVEL (small integer)\n");
+ printf(" --color=WHEN Enable colorized output (WHEN is one of 'auto', 'always', 'never')\n");
+ printf(" -h, --help Display this help and exit\n");
+ printf("\n");
+ test_list_names__();
+}
+
+int
+main(int argc, char** argv)
+{
+ const struct test__** tests = NULL;
+ int i, j, n = 0;
+ int seen_double_dash = 0;
+
+ test_argv0__ = argv[0];
+
+#if defined CUTEST_UNIX__
+ test_colorize__ = isatty(fileno(stdout));
+#elif defined CUTEST_WIN__
+ test_colorize__ = _isatty(_fileno(stdout));
+#else
+ test_colorize__ = 0;
+#endif
+
+ /* Parse options */
+ for(i = 1; i < argc; i++) {
+ if(seen_double_dash || argv[i][0] != '-') {
+ tests = (const struct test__**) realloc(tests, (n+1) * sizeof(const struct test__*));
+ if(tests == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(2);
+ }
+ tests[n] = test_by_name__(argv[i]);
+ if(tests[n] == NULL) {
+ fprintf(stderr, "%s: Unrecognized unit test '%s'\n", argv[0], argv[i]);
+ fprintf(stderr, "Try '%s --list' for list of unit tests.\n", argv[0]);
+ exit(2);
+ }
+ n++;
+ } else if(strcmp(argv[i], "--") == 0) {
+ seen_double_dash = 1;
+ } else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
+ test_help__();
+ exit(0);
+ } else if(strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
+ test_verbose_level__++;
+ } else if(strncmp(argv[i], "--verbose=", 10) == 0) {
+ test_verbose_level__ = atoi(argv[i] + 10);
+ } else if(strcmp(argv[i], "--color=auto") == 0) {
+ /* noop (set from above) */
+ } else if(strcmp(argv[i], "--color=always") == 0 || strcmp(argv[i], "--color") == 0) {
+ test_colorize__ = 1;
+ } else if(strcmp(argv[i], "--color=never") == 0) {
+ test_colorize__ = 0;
+ } else if(strcmp(argv[i], "--skip") == 0 || strcmp(argv[i], "-s") == 0) {
+ test_skip_mode__ = 1;
+ } else if(strcmp(argv[i], "--no-exec") == 0) {
+ test_no_exec__ = 1;
+ } else if(strcmp(argv[i], "--no-summary") == 0) {
+ test_no_summary__ = 1;
+ } else if(strcmp(argv[i], "--list") == 0 || strcmp(argv[i], "-l") == 0) {
+ test_list_names__();
+ exit(0);
+ } else {
+ fprintf(stderr, "%s: Unrecognized option '%s'\n", argv[0], argv[i]);
+ fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
+ exit(2);
+ }
+ }
+
+#if defined(CUTEST_WIN__)
+ SetUnhandledExceptionFilter(test_exception_filter__);
+#endif
+
+ /* Count all test units */
+ test_count__ = 0;
+ for(i = 0; test_list__[i].func != NULL; i++)
+ test_count__++;
+
+ /* Run the tests */
+ if(n == 0) {
+ /* Run all tests */
+ for(i = 0; test_list__[i].func != NULL; i++)
+ test_run__(&test_list__[i]);
+ } else if(!test_skip_mode__) {
+ /* Run the listed tests */
+ for(i = 0; i < n; i++)
+ test_run__(tests[i]);
+ } else {
+ /* Run all tests except those listed */
+ int is_skipped;
+
+ for(i = 0; test_list__[i].func != NULL; i++) {
+ is_skipped = 0;
+ for(j = 0; j < n; j++) {
+ if(tests[j] == &test_list__[i]) {
+ is_skipped = 1;
+ break;
+ }
+ }
+ if(!is_skipped)
+ test_run__(&test_list__[i]);
+ }
+ }
+
+ /* Write a summary */
+ if(!test_no_summary__ && test_verbose_level__ >= 1) {
+ test_print_in_color(CUTEST_COLOR_DEFAULT_INTENSIVE__, "\nSummary:\n");
+
+ if(test_verbose_level__ >= 3) {
+ printf(" Count of all unit tests: %4d\n", test_count__);
+ printf(" Count of run unit tests: %4d\n", test_stat_run_units__);
+ printf(" Count of failed unit tests: %4d\n", test_stat_failed_units__);
+ printf(" Count of skipped unit tests: %4d\n", test_count__ - test_stat_run_units__);
+ }
+
+ if(test_stat_failed_units__ == 0) {
+ test_print_in_color(CUTEST_COLOR_GREEN_INTENSIVE__,
+ " SUCCESS: All unit tests have passed.\n");
+ } else {
+ test_print_in_color(CUTEST_COLOR_RED_INTENSIVE__,
+ " FAILED: %d of %d unit tests have failed.\n",
+ test_stat_failed_units__, test_stat_run_units__);
+ }
+ }
+
+ if(tests != NULL)
+ free(tests);
+
+ return (test_stat_failed_units__ == 0) ? 0 : 1;
+}
+
+
+#endif /* #ifndef TEST_NO_MAIN */
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+
+#endif /* #ifndef CUTEST_H__ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/handy.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/handy.h
new file mode 100644
index 00000000..936e70f4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ext/handy.h
@@ -0,0 +1,66 @@
+#ifndef HANDY_H
+#define HANDY_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/*
+ * Handy CPP defines and C inline functions.
+ */
+
+/* Evaluates to the number of items in array-type variable arr. */
+#define ARRAYCOUNT(arr) (sizeof arr / sizeof arr[0])
+
+#ifndef MIN
+# define MIN(x, y) ((x) < (y) ? (x) : (y))
+#endif
+
+/** Stringify its argument. */
+#define STRINGIFY(x) STRINGIFY_(x)
+#define STRINGIFY_(x) #x
+
+/* Error handling macros.
+ *
+ * These expect a zero = success, non-zero = error convention.
+ */
+
+/** Error: return.
+ *
+ * If the expression fails, return the error from this function. */
+#define ER(expr) do { typeof (expr) err_ = (expr); if (err_) return err_; } while (0)
+
+/** Error: goto.
+ *
+ * If the expression fails, goto x_err. Assumes defn of label
+ * x_err and 'error_type err'. */
+#define EG(expr) do { err = (expr); if (err) goto x_err; } while (0)
+
+/** Like memset(ptr, 0, len), but not allowed to be removed by
+ * compilers. */
+static inline void mem_clean(volatile void *v, size_t len)
+{
+ if (len)
+ {
+ memset((void *) v, 0, len);
+ (void) *((volatile uint8_t *) v);
+ }
+}
+
+/** Returns 1 if len bytes at va equal len bytes at vb, 0 if they do not.
+ * Does not leak length of common prefix through timing. */
+static inline unsigned mem_eq(const void *va, const void *vb, size_t len)
+{
+ const volatile uint8_t *a = va;
+ const volatile uint8_t *b = vb;
+ uint8_t diff = 0;
+
+ while (len--)
+ {
+ diff |= *a++ ^ *b++;
+ }
+
+ return !diff;
+}
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gcm.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gcm.c
new file mode 100644
index 00000000..5b374732
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gcm.c
@@ -0,0 +1,249 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "blockwise.h"
+#include "bitops.h"
+#include "gf128.h"
+#include "tassert.h"
+
+#include <string.h>
+
+#define STATE_INVALID 0
+#define STATE_AAD 1
+#define STATE_CIPHER 2
+
+static void ghash_init(ghash_ctx *ctx, uint8_t H[16])
+{
+ memset(ctx, 0, sizeof *ctx);
+ cf_gf128_frombytes_be(H, ctx->H);
+ ctx->state = STATE_AAD;
+}
+
+static void ghash_block(void *vctx, const uint8_t *data)
+{
+ ghash_ctx *ctx = vctx;
+ cf_gf128 gfdata;
+ cf_gf128_frombytes_be(data, gfdata);
+ cf_gf128_add(gfdata, ctx->Y, ctx->Y);
+ cf_gf128_mul(ctx->Y, ctx->H, ctx->Y);
+}
+
+static void ghash_add(ghash_ctx *ctx, const uint8_t *buf, size_t n)
+{
+ cf_blockwise_accumulate(ctx->buffer, &ctx->buffer_used,
+ sizeof ctx->buffer,
+ buf, n,
+ ghash_block,
+ ctx);
+}
+
+static void ghash_add_pad(ghash_ctx *ctx)
+{
+ if (ctx->buffer_used == 0)
+ return;
+
+ memset(ctx->buffer + ctx->buffer_used, 0, sizeof(ctx->buffer) - ctx->buffer_used);
+ ghash_block(ctx, ctx->buffer);
+ ctx->buffer_used = 0;
+}
+
+static void ghash_add_aad(ghash_ctx *ctx, const uint8_t *buf, size_t n)
+{
+ assert(ctx->state == STATE_AAD);
+ ctx->len_aad += n;
+ ghash_add(ctx, buf, n);
+}
+
+static void ghash_add_cipher(ghash_ctx *ctx, const uint8_t *buf, size_t n)
+{
+ if (ctx->state == STATE_AAD)
+ {
+ ghash_add_pad(ctx);
+ ctx->state = STATE_CIPHER;
+ }
+
+ assert(ctx->state == STATE_CIPHER);
+ ctx->len_cipher += n;
+ ghash_add(ctx, buf, n);
+}
+
+static void ghash_final(ghash_ctx *ctx, uint8_t out[16])
+{
+ uint8_t lenbuf[8];
+
+ if (ctx->state == STATE_AAD || ctx->state == STATE_CIPHER)
+ {
+ ghash_add_pad(ctx);
+ ctx->state = STATE_INVALID;
+ }
+
+ /* Add len(A) || len(C) */
+ write64_be(ctx->len_aad * 8, lenbuf);
+ ghash_add(ctx, lenbuf, sizeof lenbuf);
+
+ write64_be(ctx->len_cipher * 8, lenbuf);
+ ghash_add(ctx, lenbuf, sizeof lenbuf);
+
+ assert(ctx->buffer_used == 0);
+ cf_gf128_tobytes_be(ctx->Y, out);
+}
+
+void cf_gcm_encrypt_init(const cf_prp *prp, void *prpctx, cf_gcm_ctx *gcmctx,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce)
+{
+ uint8_t H[16] = { 0 };
+
+ /* H = E_K(0^128) */
+ prp->encrypt(prpctx, H, H);
+
+ /* Produce CTR nonce, Y_0:
+ *
+ * if len(IV) == 96
+ * Y_0 = IV || 0^31 || 1
+ * otherwise
+ * Y_0 = GHASH(H, {}, IV)
+ */
+
+ if (nnonce == 12)
+ {
+ memcpy(gcmctx->Y0, nonce, nnonce);
+ gcmctx->Y0[12] = gcmctx->Y0[13] = gcmctx->Y0[14] = 0x00;
+ gcmctx->Y0[15] = 0x01;
+ } else {
+ ghash_init(&gcmctx->gh, H);
+ ghash_add_cipher(&gcmctx->gh, nonce, nnonce);
+ ghash_final(&gcmctx->gh, gcmctx->Y0);
+ }
+
+ /* Hash AAD */
+ ghash_init(&gcmctx->gh, H);
+ ghash_add_aad(&gcmctx->gh, header, nheader);
+
+ /* Produce ciphertext */
+ memset(gcmctx->e_Y0, 0, sizeof(gcmctx->e_Y0));
+ cf_ctr_init(&gcmctx->ctr, prp, prpctx, gcmctx->Y0);
+ cf_ctr_custom_counter(&gcmctx->ctr, 12, 4); /* counter is 2^32 */
+ cf_ctr_cipher(&gcmctx->ctr, gcmctx->e_Y0, gcmctx->e_Y0, sizeof gcmctx->e_Y0); /* first block is tag offset */
+
+ mem_clean(H, sizeof H);
+}
+
+void cf_gcm_encrypt_update(cf_gcm_ctx *gcmctx, const uint8_t *plain, size_t nplain, uint8_t *cipher)
+{
+ cf_ctr_cipher(&gcmctx->ctr, plain, cipher, nplain);
+ ghash_add_cipher(&gcmctx->gh, cipher, nplain);
+}
+
+void cf_gcm_encrypt_final(cf_gcm_ctx *gcmctx, uint8_t *tag, size_t ntag)
+{
+ /* Post-process ghash output */
+ uint8_t full_tag[16] = { 0 };
+ ghash_final(&gcmctx->gh, full_tag);
+
+ assert(ntag > 1 && ntag <= 16);
+ xor_bb(tag, full_tag, gcmctx->e_Y0, ntag);
+
+ mem_clean(full_tag, sizeof full_tag);
+ mem_clean(gcmctx, sizeof *gcmctx);
+}
+
+void cf_gcm_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher, /* the same size as nplain */
+ uint8_t *tag, size_t ntag)
+{
+ cf_gcm_ctx gcmctx;
+
+ cf_gcm_encrypt_init(prp, prpctx, &gcmctx, header, nheader, nonce, nnonce);
+ cf_gcm_encrypt_update(&gcmctx, plain, nplain, cipher);
+ cf_gcm_encrypt_final(&gcmctx, tag, ntag);
+}
+
+int cf_gcm_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain)
+{
+ uint8_t H[16] = { 0 };
+ uint8_t Y0[16];
+
+ /* H = E_K(0^128) */
+ prp->encrypt(prpctx, H, H);
+
+ /* Produce CTR nonce, Y_0:
+ *
+ * if len(IV) == 96
+ * Y_0 = IV || 0^31 || 1
+ * otherwise
+ * Y_0 = GHASH(H, {}, IV)
+ */
+
+ if (nnonce == 12)
+ {
+ memcpy(Y0, nonce, nnonce);
+ Y0[12] = Y0[13] = Y0[14] = 0x00;
+ Y0[15] = 0x01;
+ } else {
+ ghash_ctx gh;
+ ghash_init(&gh, H);
+ ghash_add_cipher(&gh, nonce, nnonce);
+ ghash_final(&gh, Y0);
+ }
+
+ /* Hash AAD. */
+ ghash_ctx gh;
+ ghash_init(&gh, H);
+ ghash_add_aad(&gh, header, nheader);
+
+ /* Start counter mode, to obtain offset on tag. */
+ uint8_t e_Y0[16] = { 0 };
+ cf_ctr ctr;
+ cf_ctr_init(&ctr, prp, prpctx, Y0);
+ cf_ctr_custom_counter(&ctr, 12, 4);
+ cf_ctr_cipher(&ctr, e_Y0, e_Y0, sizeof e_Y0);
+
+ /* Hash ciphertext. */
+ ghash_add_cipher(&gh, cipher, ncipher);
+
+ /* Produce tag. */
+ uint8_t full_tag[16];
+ ghash_final(&gh, full_tag);
+ assert(ntag > 1 && ntag <= 16);
+ xor_bb(full_tag, full_tag, e_Y0, ntag);
+
+ int err = 1;
+ if (!mem_eq(full_tag, tag, ntag))
+ goto x_err;
+
+ /* Complete decryption. */
+ cf_ctr_cipher(&ctr, cipher, plain, ncipher);
+ err = 0;
+
+x_err:
+ mem_clean(H, sizeof H);
+ mem_clean(Y0, sizeof Y0);
+ mem_clean(e_Y0, sizeof e_Y0);
+ mem_clean(full_tag, sizeof full_tag);
+ mem_clean(&gh, sizeof gh);
+ mem_clean(&ctr, sizeof ctr);
+ return err;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.c
new file mode 100644
index 00000000..f7ea834b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.c
@@ -0,0 +1,114 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "cf_config.h"
+#include "gf128.h"
+#include "bitops.h"
+
+#include <string.h>
+
+void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16])
+{
+ write32_be(in[0], out + 0);
+ write32_be(in[1], out + 4);
+ write32_be(in[2], out + 8);
+ write32_be(in[3], out + 12);
+}
+
+void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out)
+{
+ out[0] = read32_be(in + 0);
+ out[1] = read32_be(in + 4);
+ out[2] = read32_be(in + 8);
+ out[3] = read32_be(in + 12);
+}
+
+/* out = 2 * in. Arguments may alias. */
+void cf_gf128_double(const cf_gf128 in, cf_gf128 out)
+{
+ uint8_t table[2] = { 0x00, 0x87 };
+ uint32_t borrow = 0;
+ uint32_t inword;
+
+ inword = in[3]; out[3] = (inword << 1) | borrow; borrow = inword >> 31;
+ inword = in[2]; out[2] = (inword << 1) | borrow; borrow = inword >> 31;
+ inword = in[1]; out[1] = (inword << 1) | borrow; borrow = inword >> 31;
+ inword = in[0]; out[0] = (inword << 1) | borrow; borrow = inword >> 31;
+
+#if CF_CACHE_SIDE_CHANNEL_PROTECTION
+ out[3] ^= select_u8(borrow, table, 2);
+#else
+ out[3] ^= table[borrow];
+#endif
+}
+
+/* out = 2 * in. Arguments may alias. */
+void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out)
+{
+ uint8_t table[2] = { 0x00, 0xe1 };
+ uint32_t borrow = 0;
+ uint32_t inword;
+
+ inword = in[0]; out[0] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
+ inword = in[1]; out[1] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
+ inword = in[2]; out[2] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
+ inword = in[3]; out[3] = (inword >> 1) | (borrow << 31); borrow = inword & 1;
+
+#if CF_CACHE_SIDE_CHANNEL_PROTECTION
+ out[0] ^= select_u8(borrow, table, 2) << 24;
+#else
+ out[0] ^= table[borrow] << 24;
+#endif
+}
+
+/* out = x + y. Arguments may alias. */
+void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out)
+{
+ out[0] = x[0] ^ y[0];
+ out[1] = x[1] ^ y[1];
+ out[2] = x[2] ^ y[2];
+ out[3] = x[3] ^ y[3];
+}
+
+/* out = xy. Arguments may alias. */
+void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out)
+{
+#if CF_TIME_SIDE_CHANNEL_PROTECTION
+ cf_gf128 zero = { 0 };
+#endif
+
+ /* Z_0 = 0^128
+ * V_0 = Y */
+ cf_gf128 Z, V;
+ memset(Z, 0, sizeof Z);
+ memcpy(V, y, sizeof V);
+
+ int i;
+ for (i = 0; i < 128; i++)
+ {
+ uint32_t word = x[i >> 5];
+ uint8_t bit = (word >> (31 - (i & 31))) & 1;
+
+#if CF_TIME_SIDE_CHANNEL_PROTECTION
+ select_xor128(Z, zero, V, bit);
+#else
+ if (bit)
+ xor_words(Z, V, 4);
+#endif
+
+ cf_gf128_double_le(V, V);
+ }
+
+ memcpy(out, Z, sizeof Z);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.h
new file mode 100644
index 00000000..75608623
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/gf128.h
@@ -0,0 +1,55 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef GF128_H
+#define GF128_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * @brief Operations in GF(2^128).
+ *
+ * These implementations are constant time, but relatively slow.
+ */
+
+typedef uint32_t cf_gf128[4];
+
+/* Unpack from big-endian bytes into out. */
+void cf_gf128_frombytes_be(const uint8_t in[16], cf_gf128 out);
+
+/* Pack in big-endian order into out. */
+void cf_gf128_tobytes_be(const cf_gf128 in, uint8_t out[16]);
+
+/* out = 2 * in. Arguments may not alias. */
+void cf_gf128_double(const cf_gf128 in, cf_gf128 out);
+
+/* out = 2 * in. Arguments may not alias.
+ * This differs from cf_gf128_double because it interprets the
+ * block in little endian: the lsb is the msb of the
+ * first element, the msb is the lsb of the last element.
+ *
+ * GCM uses this convention. */
+void cf_gf128_double_le(const cf_gf128 in, cf_gf128 out);
+
+/* out = x + y. Arguments may alias. */
+void cf_gf128_add(const cf_gf128 x, const cf_gf128 y, cf_gf128 out);
+
+/* out = xy. Arguments may alias.
+ *
+ * This uses cf_gf128_double_le internally, and is suitable for
+ * GCM. */
+void cf_gf128_mul(const cf_gf128 x, const cf_gf128 y, cf_gf128 out);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.c
new file mode 100644
index 00000000..98646d7e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.c
@@ -0,0 +1,106 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "hmac.h"
+#include "chash.h"
+#include "bitops.h"
+#include "handy.h"
+#include "tassert.h"
+
+#include <string.h>
+
+void cf_hmac_init(cf_hmac_ctx *ctx,
+ const cf_chash *hash,
+ const uint8_t *key, size_t nkey)
+{
+ assert(ctx);
+ assert(hash);
+
+ mem_clean(ctx, sizeof *ctx);
+ ctx->hash = hash;
+
+ /* Prepare key: */
+ uint8_t k[CF_CHASH_MAXBLK];
+
+ /* Shorten long keys. */
+ if (nkey > hash->blocksz)
+ {
+ /* Standard doesn't cover case where blocksz < hashsz.
+ * FIPS186-1 seems to want to append a negative number of zero bytes.
+ * In any case, we only have a k buffer of CF_CHASH_MAXBLK! */
+ assert(hash->hashsz <= hash->blocksz);
+
+ cf_hash(hash, key, nkey, k);
+ key = k;
+ nkey = hash->hashsz;
+ }
+
+ /* Right zero-pad short keys. */
+ if (k != key)
+ memcpy(k, key, nkey);
+ if (hash->blocksz > nkey)
+ memset(k + nkey, 0, hash->blocksz - nkey);
+
+ /* Start inner hash computation */
+ uint8_t blk[CF_CHASH_MAXBLK];
+
+ xor_b8(blk, k, 0x36, hash->blocksz);
+ hash->init(&ctx->inner);
+ hash->update(&ctx->inner, blk, hash->blocksz);
+
+ /* And outer. */
+ xor_b8(blk, k, 0x5c, hash->blocksz);
+ hash->init(&ctx->outer);
+ hash->update(&ctx->outer, blk, hash->blocksz);
+
+ mem_clean(blk, sizeof blk);
+ mem_clean(k, sizeof k);
+}
+
+void cf_hmac_update(cf_hmac_ctx *ctx, const void *data, size_t ndata)
+{
+ assert(ctx && ctx->hash);
+
+ ctx->hash->update(&ctx->inner, data, ndata);
+}
+
+void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out)
+{
+ assert(ctx && ctx->hash);
+ assert(out);
+
+ uint8_t innerh[CF_MAXHASH];
+ ctx->hash->digest(&ctx->inner, innerh);
+
+ ctx->hash->update(&ctx->outer, innerh, ctx->hash->hashsz);
+ ctx->hash->digest(&ctx->outer, out);
+
+ mem_clean(ctx, sizeof *ctx);
+}
+
+void cf_hmac(const uint8_t *key, size_t nkey,
+ const uint8_t *msg, size_t nmsg,
+ uint8_t *out,
+ const cf_chash *hash)
+{
+ cf_hmac_ctx ctx;
+
+ assert(out);
+ assert(hash);
+
+ cf_hmac_init(&ctx, hash, key, nkey);
+ cf_hmac_update(&ctx, msg, nmsg);
+ cf_hmac_finish(&ctx, out);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.h
new file mode 100644
index 00000000..2f9ea7b0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/hmac.h
@@ -0,0 +1,78 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef HMAC_H
+#define HMAC_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "chash.h"
+
+/**
+ * HMAC
+ * ====
+ * This is a one-shot and incremental interface to computing
+ * HMAC with any hash function.
+ *
+ * (Note: HMAC with SHA3 is possible, but is probably not a
+ * sensible thing to want.)
+ */
+
+/* .. c:type:: cf_hmac_ctx
+ * HMAC incremental interface context.
+ *
+ * .. c:member:: cf_hmac_ctx.hash
+ * Hash function description.
+ *
+ * .. c:member:: cf_hmac_ctx.inner
+ * Inner hash computation.
+ *
+ * .. c:member:: cf_hmac_ctx.outer
+ * Outer hash computation.
+ */
+typedef struct
+{
+ const cf_chash *hash;
+ cf_chash_ctx inner;
+ cf_chash_ctx outer;
+} cf_hmac_ctx;
+
+/* .. c:function:: $DECL
+ * Set up ctx for computing a HMAC using the given hash and key. */
+void cf_hmac_init(cf_hmac_ctx *ctx,
+ const cf_chash *hash,
+ const uint8_t *key, size_t nkey);
+
+/* .. c:function:: $DECL
+ * Input data. */
+void cf_hmac_update(cf_hmac_ctx *ctx,
+ const void *data, size_t ndata);
+
+/* .. c:function:: $DECL
+ * Finish and compute HMAC.
+ * `ctx->hash->hashsz` bytes are written to `out`. */
+void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out);
+
+/* .. c:function:: $DECL
+ * One shot interface: compute `HMAC_hash(key, msg)`, writing the
+ * answer (which is `hash->hashsz` long) to `out`.
+ *
+ * This function does not fail. */
+void cf_hmac(const uint8_t *key, size_t nkey,
+ const uint8_t *msg, size_t nmsg,
+ uint8_t *out,
+ const cf_chash *hash);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.c
new file mode 100644
index 00000000..1e44af1d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.c
@@ -0,0 +1,99 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "prp.h"
+#include "modes.h"
+#include "bitops.h"
+#include "blockwise.h"
+
+#include <string.h>
+#include "tassert.h"
+
+/* CBC */
+void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK])
+{
+ ctx->prp = prp;
+ ctx->prpctx = prpctx;
+ memcpy(ctx->block, iv, prp->blocksz);
+}
+
+void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks)
+{
+ uint8_t buf[CF_MAXBLOCK];
+ size_t nblk = ctx->prp->blocksz;
+
+ while (blocks--)
+ {
+ xor_bb(buf, input, ctx->block, nblk);
+ ctx->prp->encrypt(ctx->prpctx, buf, ctx->block);
+ memcpy(output, ctx->block, nblk);
+ input += nblk;
+ output += nblk;
+ }
+}
+
+void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks)
+{
+ uint8_t buf[CF_MAXBLOCK];
+ size_t nblk = ctx->prp->blocksz;
+
+ while (blocks--)
+ {
+ ctx->prp->decrypt(ctx->prpctx, input, buf);
+ xor_bb(output, buf, ctx->block, nblk);
+ memcpy(ctx->block, input, nblk);
+ input += nblk;
+ output += nblk;
+ }
+}
+
+/* CTR */
+void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK])
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->counter_offset = 0;
+ ctx->counter_width = prp->blocksz;
+ ctx->prp = prp;
+ ctx->prpctx = prpctx;
+ ctx->nkeymat = 0;
+ memcpy(ctx->nonce, nonce, prp->blocksz);
+}
+
+void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width)
+{
+ assert(ctx->prp->blocksz <= offset + width);
+ ctx->counter_offset = offset;
+ ctx->counter_width = width;
+}
+
+static void ctr_next_block(void *vctx, uint8_t *out)
+{
+ cf_ctr *ctx = vctx;
+ ctx->prp->encrypt(ctx->prpctx, ctx->nonce, out);
+ incr_be(ctx->nonce + ctx->counter_offset, ctx->counter_width);
+}
+
+void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes)
+{
+ cf_blockwise_xor(ctx->keymat, &ctx->nkeymat,
+ ctx->prp->blocksz,
+ input, output, bytes,
+ ctr_next_block,
+ ctx);
+}
+
+void cf_ctr_discard_block(cf_ctr *ctx)
+{
+ ctx->nkeymat = 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.h
new file mode 100644
index 00000000..20940a34
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/modes.h
@@ -0,0 +1,587 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef MODES_H
+#define MODES_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "gf128.h"
+#include "prp.h"
+
+/**
+ * Block cipher modes
+ * ==================
+ */
+
+/**
+ * CBC mode
+ * --------
+ * This implementation allows encryption or decryption of whole
+ * blocks in CBC mode. It does not offer a byte-wise incremental
+ * interface, or do any padding.
+ *
+ * This mode provides no useful integrity and should not be used
+ * directly.
+ */
+
+/* .. c:type:: cf_cbc
+ * This structure binds together the things needed to encrypt/decrypt whole
+ * blocks in CBC mode.
+ *
+ * .. c:member:: cf_cbc.prp
+ * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
+ *
+ * .. c:member:: cf_cbc.prpctx
+ * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
+ * pointer to a :c:type:`cf_aes_context` instance.
+ *
+ * .. c:member:: cf_cbc.block
+ * The IV or last ciphertext block.
+ */
+typedef struct
+{
+ const cf_prp *prp;
+ void *prpctx;
+ uint8_t block[CF_MAXBLOCK];
+} cf_cbc;
+
+/* .. c:function:: $DECL
+ * Initialise CBC encryption/decryption context using selected prp, prp context and IV. */
+void cf_cbc_init(cf_cbc *ctx, const cf_prp *prp, void *prpctx, const uint8_t iv[CF_MAXBLOCK]);
+
+/* .. c:function:: $DECL
+ * Encrypt blocks in CBC mode. input and output
+ * must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */
+void cf_cbc_encrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks);
+
+/* .. c:function:: $DECL
+ * Decrypt blocks in CBC mode. input and output
+ * must point to blocks * ctx->prp->blocksz bytes of storage (and may alias). */
+void cf_cbc_decrypt(cf_cbc *ctx, const uint8_t *input, uint8_t *output, size_t blocks);
+
+/**
+ * Counter mode
+ * ------------
+ * This implementation allows incremental encryption/decryption of
+ * messages. Encryption and decryption are the same operation.
+ *
+ * The counter is always big-endian, but has configurable location
+ * and size within the nonce block. The counter wraps, so you
+ * should make sure the length of a message with a given nonce
+ * doesn't cause nonce reuse.
+ *
+ * This mode provides no integrity and should not be used directly.
+ */
+
+/* .. c:type:: cf_ctr
+ *
+ * .. c:member:: cf_ctr.prp
+ * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
+ *
+ * .. c:member:: cf_ctr.prpctx
+ * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
+ * pointer to a :c:type:`cf_aes_context` instance.
+ *
+ * .. c:member:: cf_ctr.nonce
+ * The next block to encrypt to get another block of key stream.
+ *
+ * .. c:member:: cf_ctr.keymat
+ * The current block of key stream.
+ *
+ * .. c:member:: cf_ctr.nkeymat
+ * The number of bytes at the end of :c:member:`keymat` that are so-far unused.
+ * If this is zero, all the bytes are used up and/or of undefined value.
+ *
+ * .. c:member:: cf_ctr.counter_offset
+ * The offset (in bytes) of the counter block within the nonce.
+ *
+ * .. c:member:: cf_ctr.counter_width
+ * The width (in bytes) of the counter block in the nonce.
+ */
+typedef struct
+{
+ const cf_prp *prp;
+ void *prpctx;
+ uint8_t nonce[CF_MAXBLOCK];
+ uint8_t keymat[CF_MAXBLOCK];
+ size_t nkeymat;
+ size_t counter_offset;
+ size_t counter_width;
+} cf_ctr;
+
+/* .. c:function:: $DECL
+ * Initialise CTR encryption/decryption context using selected prp and nonce.
+ * (nb, this only increments the whole nonce as a big endian block) */
+void cf_ctr_init(cf_ctr *ctx, const cf_prp *prp, void *prpctx, const uint8_t nonce[CF_MAXBLOCK]);
+
+/* .. c:function:: $DECL
+ * Set the location and width of the nonce counter.
+ *
+ * eg. offset = 12, width = 4 means the counter is mod 2^32 and placed
+ * at the end of the nonce. */
+void cf_ctr_custom_counter(cf_ctr *ctx, size_t offset, size_t width);
+
+/* .. c:function:: $DECL
+ * Encrypt or decrypt bytes in CTR mode.
+ * input and output may alias and must point to specified number of bytes. */
+void cf_ctr_cipher(cf_ctr *ctx, const uint8_t *input, uint8_t *output, size_t bytes);
+
+/* .. c:function:: $DECL
+ * Discards the rest of this block of key stream. */
+void cf_ctr_discard_block(cf_ctr *ctx);
+
+/**
+ * CBC-MAC
+ * -------
+ * This is a incremental interface to computing a CBC-MAC tag over a message.
+ *
+ * It optionally pads the message with PKCS#5/PKCS#7 padding -- if you don't
+ * do this, messages must be an exact number of blocks long.
+ *
+ * You shouldn't use this directly because it isn't secure for variable-length
+ * messages. Use CMAC instead.
+ */
+
+/* .. c:type:: cf_cbcmac_stream
+ * Stream interface to CBC-MAC signing.
+ *
+ * .. c:member:: cf_cbcmac.prp
+ * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
+ *
+ * .. c:member:: cf_cbcmac.prpctx
+ * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
+ * pointer to a :c:type:`cf_aes_context` instance.
+ *
+ * .. c:member:: cf_cbcmac.cbc
+ * CBC data.
+ *
+ * .. c:member:: cf_cbcmac.buffer
+ * Buffer for data which can't be processed until we have a full block.
+ *
+ * .. c:member:: cf_cbcmac.used
+ * How many bytes at the front of :c:member:`buffer` are valid.
+ */
+typedef struct
+{
+ const cf_prp *prp;
+ void *prpctx;
+ cf_cbc cbc;
+ uint8_t buffer[CF_MAXBLOCK];
+ size_t used;
+} cf_cbcmac_stream;
+
+/* .. c:function:: $DECL
+ * Initialise CBC-MAC signing context using selected prp. */
+void cf_cbcmac_stream_init(cf_cbcmac_stream *ctx, const cf_prp *prp, void *prpctx);
+
+/* .. c:function:: $DECL
+ * Reset the streaming signing context, to sign a new message. */
+void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx);
+
+/* .. c:function:: $DECL
+ * Process ndata bytes at data. */
+void cf_cbcmac_stream_update(cf_cbcmac_stream *ctx, const uint8_t *data, size_t ndata);
+
+/* .. c:function:: $DECL
+ * Finish the current block of data by adding zeroes. Does nothing if there
+ * are no bytes awaiting processing. */
+void cf_cbcmac_stream_finish_block_zero(cf_cbcmac_stream *ctx);
+
+/* .. c:function:: $DECL
+ * Output the MAC to ctx->prp->blocksz bytes at out.
+ * ctx->used must be zero: the inputed message must be an exact number of
+ * blocks. */
+void cf_cbcmac_stream_nopad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
+
+/* .. c:function:: $DECL
+ * Output the MAC to ctx->prp->blocksz bytes at out.
+ *
+ * The message is padded with PKCS#5 padding. */
+void cf_cbcmac_stream_pad_final(cf_cbcmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
+
+/**
+ * CMAC
+ * ----
+ * This is both a one-shot and incremental interface to
+ * computing a CMAC tag over a message.
+ *
+ * The one-shot interface separates out the per-key computation,
+ * so if you need to compute lots of MACs with one key you don't
+ * pay that cost more than once.
+ *
+ * CMAC is a good choice for a symmetric MAC.
+ */
+
+/* .. c:type:: cf_cmac
+ * One-shot interface to CMAC signing.
+ *
+ * .. c:member:: cf_cmac.prp
+ * How to encrypt or decrypt blocks. This could be, for example, :c:data:`cf_aes`.
+ *
+ * .. c:member:: cf_cmac.prpctx
+ * Private data for prp functions. For a `prp` of `cf_aes`, this would be a
+ * pointer to a :c:type:`cf_aes_context` instance.
+ *
+ * .. c:member:: cf_cmac.B
+ * The XOR offset for the last message block if it is a complete block
+ * (also known as K\ :sub:`1`).
+ *
+ * .. c:member:: cf_cmac.P
+ * The XOR offset for the last message block if it is a partial block
+ * (also known as K\ :sub:`2`).
+ */
+typedef struct
+{
+ const cf_prp *prp;
+ void *prpctx;
+ uint8_t B[CF_MAXBLOCK];
+ uint8_t P[CF_MAXBLOCK];
+} cf_cmac;
+
+/* .. c:function:: $DECL
+ * Initialise CMAC signing context using selected prp. */
+void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx);
+
+/* .. c:function:: $DECL
+ * CMAC sign the given data. The MAC is written to ctx->prp->blocksz
+ * bytes at out. This is a one-shot function. */
+void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t bytes,
+ uint8_t out[CF_MAXBLOCK]);
+
+/* .. c:type:: cf_cmac_stream
+ * Stream interface to CMAC signing.
+ *
+ * Input data in arbitrary chunks using :c:func:`cf_cmac_stream_update`.
+ * The last bit of data must be signalled with the `isfinal` flag to
+ * that function, and the data cannot be zero length unless the whole
+ * message is empty.
+ *
+ * .. c:member:: cf_cmac_stream.cmac
+ * CMAC one-shot data.
+ *
+ * .. c:member:: cf_cmac_stream.cbc
+ * CBC block encryption data.
+ *
+ * .. c:member:: cf_cmac_stream.buffer
+ * Buffer for data which can't be processed until we have a full block.
+ *
+ * .. c:member:: cf_cmac_stream.used
+ * How many bytes at the front of :c:member:`buffer` are valid.
+ *
+ * .. c:member:: cf_cmac_stream.processed
+ * How many bytes in total we've processed. This is used to correctly
+ * process empty messages.
+ *
+ * .. c:member:: cf_cmac_stream.finalised
+ * A flag set when the final chunk of the message has been processed.
+ * Only when this flag is set can you get the MAC out.
+ */
+typedef struct
+{
+ cf_cmac cmac;
+ cf_cbc cbc;
+ uint8_t buffer[CF_MAXBLOCK];
+ size_t used;
+ size_t processed;
+ int finalised;
+} cf_cmac_stream;
+
+/* .. c:function:: $DECL
+ * Initialise CMAC streaming signing context using selected prp. */
+void cf_cmac_stream_init(cf_cmac_stream *ctx, const cf_prp *prp, void *prpctx);
+
+/* .. c:function:: $DECL
+ * Reset the streaming signing context, to sign a new message. */
+void cf_cmac_stream_reset(cf_cmac_stream *ctx);
+
+/* .. c:function:: $DECL
+ * Process ndata bytes at data. isfinal is non-zero if this is the last piece
+ * of data. */
+void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t ndata,
+ int isfinal);
+
+/* .. c:function:: $DECL
+ * Output the MAC to ctx->cmac->prp->blocksz bytes at out.
+ * cf_cmac_stream_update with isfinal non-zero must have been called
+ * since the last _init/_reset. */
+void cf_cmac_stream_final(cf_cmac_stream *ctx, uint8_t out[CF_MAXBLOCK]);
+
+/**
+ * EAX
+ * ---
+ *
+ * The EAX authenticated encryption mode. This is a one-shot
+ * interface.
+ *
+ * EAX is a pretty respectable and fast AEAD mode.
+ */
+
+/* .. c:function:: $DECL
+ * EAX authenticated encryption.
+ *
+ * This function does not fail.
+ *
+ * :param prp/prpctx: describe the block cipher to use.
+ * :param plain: message plaintext.
+ * :param nplain: length of message. May be zero.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD. May be zero.
+ * :param nonce: nonce. This must not repeat for a given key.
+ * :param nnonce: length of nonce. The nonce can be any length.
+ * :param cipher: ciphertext output. `nplain` bytes are written here.
+ * :param tag: authentication tag. `ntag` bytes are written here.
+ * :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`.
+ */
+void cf_eax_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher,
+ uint8_t *tag, size_t ntag);
+
+/* .. c:function:: $DECL
+ * EAX authenticated decryption.
+ *
+ * :return: 0 on success, non-zero on error. Nothing is written to plain on error.
+ *
+ * :param prp/prpctx: describe the block cipher to use.
+ * :param cipher: message ciphertext.
+ * :param ncipher: message length.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD.
+ * :param nonce: nonce.
+ * :param nnonce: length of nonce.
+ * :param tag: authentication tag. `ntag` bytes are read from here.
+ * :param ntag: authentication tag length.
+ * :param plain: plaintext output. `ncipher` bytes are written here.
+ */
+int cf_eax_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain);
+
+/**
+ * GCM
+ * ---
+ * The GCM ('Galois counter mode') authenticated encryption mode.
+ * This is a one-shot interface.
+ *
+ * GCM is a reasonably respectable AEAD mode. It's somewhat more
+ * complex than EAX, and side channel-free implementations can
+ * be quite slow.
+ */
+
+/* .. c:function:: $DECL
+ * GCM authenticated encryption.
+ *
+ * This function does not fail.
+ *
+ * :param prp/prpctx: describe the block cipher to use.
+ * :param plain: message plaintext.
+ * :param nplain: length of message. May be zero.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD. May be zero.
+ * :param nonce: nonce. This must not repeat for a given key.
+ * :param nnonce: length of nonce. The nonce can be any length, but 12 bytes is strongly recommended.
+ * :param cipher: ciphertext output. `nplain` bytes are written here.
+ * :param tag: authentication tag. `ntag` bytes are written here.
+ * :param ntag: authentication tag length. This must be non-zero and no greater than `prp->blocksz`.
+ *
+ * This function does not fail.
+ */
+void cf_gcm_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher,
+ uint8_t *tag, size_t ntag);
+
+/* Incremental GHASH computation. */
+typedef struct
+{
+ cf_gf128 H;
+ cf_gf128 Y;
+ uint8_t buffer[16];
+ size_t buffer_used;
+ uint64_t len_aad;
+ uint64_t len_cipher;
+ unsigned state;
+} ghash_ctx;
+
+typedef struct
+{
+ cf_ctr ctr;
+ ghash_ctx gh;
+ uint8_t Y0[16];
+ uint8_t e_Y0[16];
+} cf_gcm_ctx;
+
+void cf_gcm_encrypt_init(const cf_prp *prp, void *prpctx, cf_gcm_ctx *gcmctx,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce);
+void cf_gcm_encrypt_update(cf_gcm_ctx *gcmctx, const uint8_t *plain, size_t nplain, uint8_t *cipher);
+void cf_gcm_encrypt_final(cf_gcm_ctx *gcmctx, uint8_t *tag, size_t ntag);
+
+/* .. c:function:: $DECL
+ * GCM authenticated decryption.
+ *
+ * :return: 0 on success, non-zero on error. Nothing is written to plain on error.
+ *
+ * :param prp: describe the block cipher to use.
+ * :param prpctx: describe the block cipher to use.
+ * :param cipher: message ciphertext.
+ * :param ncipher: message length.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD.
+ * :param nonce: nonce.
+ * :param nnonce: length of nonce.
+ * :param tag: authentication tag. `ntag` bytes are read from here.
+ * :param ntag: authentication tag length.
+ * :param plain: plaintext output. `ncipher` bytes are written here.
+ */
+int cf_gcm_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain);
+
+/**
+ * CCM
+ * ---
+ *
+ * The CCM ('Counter with CBC-MAC') authenticated encryption mode.
+ * CCM is a widely used AEAD mode (in IPSec, WPA2, Bluetooth, etc.)
+ *
+ * It works (at a high level) by just gluing together CTR and CBC-MAC
+ * modes (in MAC-then-encrypt mode) and then fixing the problems inherent
+ * with CBC-MAC in over-complicated ways.
+ *
+ * This is a one-shot interface, which is good because the underlying
+ * mechanism isn't actually online: you need to know the message length
+ * before you start, or do everything in two passes.
+ */
+
+/* .. c:function:: $DECL
+ * CCM authenticated encryption.
+ *
+ * This function does not fail.
+ *
+ * :param prp/prpctx: describe the block cipher to use.
+ * :param plain: message plaintext.
+ * :param nplain: length of message. May be zero. Must meet the constraints placed on it by `L`.
+ * :param L: length of the message length encoding. This must be in the interval `[2,8]` and gives a maximum message size of 2\ :sup:`8L` bytes.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD. May be zero.
+ * :param nonce: nonce. This must not repeat for a given key.
+ * :param nnonce: length of nonce. Must be exactly `15 - L` bytes for a 128-bit block cipher.
+ * :param cipher: ciphertext output. `nplain` bytes are written here.
+ * :param tag: authentication tag. `ntag` bytes are written here.
+ * :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16.
+ */
+void cf_ccm_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain, size_t L,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher,
+ uint8_t *tag, size_t ntag);
+
+/* .. c:function:: $DECL
+ * CCM authenticated decryption.
+ *
+ * :return: 0 on success, non-zero on error. Plain is cleared on error.
+ *
+ * :param prp: describe the block cipher to use.
+ * :param prpctx: describe the block cipher to use.
+ * :param cipher: message ciphertext.
+ * :param ncipher: length of message.
+ * :param L: length of the message length encoding. See :c:func:`cf_ccm_encrypt`.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD.
+ * :param nonce: nonce.
+ * :param nnonce: length of nonce.
+ * :param tag: authentication tag. `ntag` bytes are read from here.
+ * :param ntag: authentication tag length. This must be 4, 6, 8, 10, 12, 14 or 16.
+ * :param plain: plaintext output. `ncipher` bytes are written here.
+ */
+int cf_ccm_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher, size_t L,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain);
+
+/**
+ * OCB
+ * ---
+ *
+ * OCB is an authenticated encryption mode by Phil Rogaway.
+ *
+ * This is version 3, as standardised in RFC7253. It's defined
+ * only for block ciphers with a 128-bit block size.
+ *
+ * This is a one-shot interface.
+ */
+
+/* .. c:function:: $DECL
+ * OCB authenticated encryption.
+ *
+ * This function does not fail.
+ *
+ * :param prp/prpctx: describe the block cipher to use.
+ * :param plain: message plaintext.
+ * :param nplain: length of message. May be zero.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD. May be zero.
+ * :param nonce: nonce. This must not repeat for a given key.
+ * :param nnonce: length of nonce. Must be 15 or fewer bytes.
+ * :param cipher: ciphertext output. `nplain` bytes are written here.
+ * :param tag: authentication tag. `ntag` bytes are written here.
+ * :param ntag: authentication tag length. Must be 16 or fewer bytes.
+ */
+void cf_ocb_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher,
+ uint8_t *tag, size_t ntag);
+
+/* .. c:function:: $DECL
+ * OCB authenticated decryption.
+ *
+ * :return: 0 on success, non-zero on error. `plain` is cleared on error.
+ *
+ * :param prp: describe the block cipher to use.
+ * :param prpctx: describe the block cipher to use.
+ * :param cipher: message ciphertext.
+ * :param ncipher: length of message.
+ * :param header: additionally authenticated data (AAD).
+ * :param nheader: length of AAD.
+ * :param nonce: nonce.
+ * :param nnonce: length of nonce.
+ * :param tag: authentication tag. `ntag` bytes are read from here.
+ * :param ntag: authentication tag length.
+ * :param plain: plaintext output. `ncipher` bytes are written here.
+ */
+int cf_ocb_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain);
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.c
new file mode 100644
index 00000000..8f0aba6b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.c
@@ -0,0 +1,410 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+
+#include "norx.h"
+#include "bitops.h"
+#include "handy.h"
+#include "blockwise.h"
+#include "tassert.h"
+
+#include <string.h>
+
+typedef struct
+{
+ uint32_t s[16];
+} norx32_ctx;
+
+/* Domain separation constants */
+#define DOMAIN_HEADER 0x01
+#define DOMAIN_PAYLOAD 0x02
+#define DOMAIN_TRAILER 0x04
+#define DOMAIN_TAG 0x08
+
+#define WORD_BYTES 4
+#define WORD_BITS 32
+#define ROUNDS 4
+#define DEGREE 1
+#define TAG_BITS 128
+#define RATE_BYTES 48
+#define RATE_WORDS 12
+
+static void permute(norx32_ctx *ctx)
+{
+#ifdef CORTEX_M0
+ /* Register usage: A-D r2, r3, r4, r5.
+ * Temps: r6 */
+
+#define in(xx) "%[" #xx "]"
+
+ /* Load numbered slots of S into r2-r5 */
+#define LOAD(u, v, w, x) \
+ " ldr r2, [%[S], " in(u) "]\n" \
+ " ldr r3, [%[S], " in(v) "]\n" \
+ " ldr r4, [%[S], " in(w) "]\n" \
+ " ldr r5, [%[S], " in(x) "]\n"
+
+ /* Store r2-r5 into numbered slots of S */
+#define STORE(u, v, w, x) \
+ " str r2, [%[S], " in(u) "]\n" \
+ " str r3, [%[S], " in(v) "]\n" \
+ " str r4, [%[S], " in(w) "]\n" \
+ " str r5, [%[S], " in(x) "]\n"
+
+ /* This is H() plus the xor and rotate in one step of G.
+ * rx is the register containing x (read/write)
+ * ry is the register containing y (read)
+ * rw is the register containing d (read/write)
+ * rot is the rotation constant r_n */
+#define P(rx, ry, rw, rot) \
+ " mov r6, " #rx "\n" \
+ " and " #rx ", " #ry "\n" \
+ " lsl " #rx ", #1\n" \
+ " eor " #rx ", r6\n" \
+ " eor " #rx ", " #ry "\n" \
+ " mov r6, #" #rot "\n" \
+ " eor " #rw ", " #rx "\n" \
+ " ror " #rw ", r6\n"
+
+ /* The function G. s is the state array, a-d are indices
+ * into it. */
+#define G(s, a, b, c, d) \
+ __asm__ ( \
+ LOAD(A, B, C, D) \
+ P(r2, r3, r5, 8) \
+ P(r4, r5, r3, 11) \
+ P(r2, r3, r5, 16) \
+ P(r4, r5, r3, 31) \
+ STORE(A, B, C, D) \
+ : \
+ : [S] "r" (s), \
+ [A] "i" (a << 2), \
+ [B] "i" (b << 2), \
+ [C] "i" (c << 2), \
+ [D] "i" (d << 2) \
+ : "memory", "cc", "r2", "r3", "r4", "r5", "r6");
+#else
+
+ /* This is one quarter of G; the function H plus xor/rotate. */
+#define P(u, v, w, rr) \
+ (u) = ((u) ^ (v)) ^ (((u) & (v)) << 1); \
+ (w) = rotr32((u) ^ (w), rr);
+
+#define G(s, a, b, c, d) \
+ P(s[a], s[b], s[d], 8) \
+ P(s[c], s[d], s[b], 11) \
+ P(s[a], s[b], s[d], 16) \
+ P(s[c], s[d], s[b], 31)
+#endif
+
+ for (int i = 0; i < ROUNDS; i++)
+ {
+ /* columns */
+ G(ctx->s, 0, 4, 8, 12);
+ G(ctx->s, 1, 5, 9, 13);
+ G(ctx->s, 2, 6, 10, 14);
+ G(ctx->s, 3, 7, 11, 15);
+
+ /* diagonals */
+ G(ctx->s, 0, 5, 10, 15);
+ G(ctx->s, 1, 6, 11, 12);
+ G(ctx->s, 2, 7, 8, 13);
+ G(ctx->s, 3, 4, 9, 14);
+ }
+
+#undef G
+#undef P
+}
+
+static void init(norx32_ctx *ctx,
+ const uint8_t key[16],
+ const uint8_t nonce[8])
+{
+ /* 1. Basic setup */
+ ctx->s[0] = read32_le(nonce + 0);
+ ctx->s[1] = read32_le(nonce + 4);
+ ctx->s[2] = 0xb707322f;
+ ctx->s[3] = 0xa0c7c90d;
+
+ ctx->s[4] = read32_le(key + 0);
+ ctx->s[5] = read32_le(key + 4);
+ ctx->s[6] = read32_le(key + 8);
+ ctx->s[7] = read32_le(key + 12);
+
+ ctx->s[8] = 0xa3d8d930;
+ ctx->s[9] = 0x3fa8b72c;
+ ctx->s[10] = 0xed84eb49;
+ ctx->s[11] = 0xedca4787;
+
+ ctx->s[12] = 0x335463eb;
+ ctx->s[13] = 0xf994220b;
+ ctx->s[14] = 0xbe0bf5c9;
+ ctx->s[15] = 0xd7c49104;
+
+ /* 2. Parameter integration
+ * w = 32
+ * l = 4
+ * p = 1
+ * t = 128
+ */
+ ctx->s[12] ^= WORD_BITS;
+ ctx->s[13] ^= ROUNDS;
+ ctx->s[14] ^= DEGREE;
+ ctx->s[15] ^= TAG_BITS;
+
+ permute(ctx);
+}
+
+/* Input domain separation constant for next step, and final permutation of
+ * preceeding step. */
+static void switch_domain(norx32_ctx *ctx, uint32_t constant)
+{
+ ctx->s[15] ^= constant;
+ permute(ctx);
+}
+
+typedef struct
+{
+ norx32_ctx *ctx;
+ uint32_t type;
+} blockctx;
+
+static void input_block_final(void *vctx, const uint8_t *data)
+{
+ blockctx *bctx = vctx;
+ norx32_ctx *ctx = bctx->ctx;
+
+ /* just xor-in data. */
+ for (int i = 0; i < RATE_WORDS; i++)
+ {
+ ctx->s[i] ^= read32_le(data);
+ data += WORD_BYTES;
+ }
+}
+
+static void input_block(void *vctx, const uint8_t *data)
+{
+ /* Process block, then prepare for the next one. */
+ blockctx *bctx = vctx;
+ input_block_final(vctx, data);
+ switch_domain(bctx->ctx, bctx->type);
+}
+
+static void input(norx32_ctx *ctx, uint32_t type,
+ const uint8_t *buf, size_t nbuf)
+{
+ uint8_t partial[RATE_BYTES];
+ size_t npartial = 0;
+ blockctx bctx = { ctx, type };
+
+ /* Process input. */
+ cf_blockwise_accumulate(partial, &npartial, sizeof partial,
+ buf, nbuf,
+ input_block,
+ &bctx);
+
+ /* Now pad partial. This contains the trailing portion of buf. */
+ memset(partial + npartial, 0, sizeof(partial) - npartial);
+ partial[npartial] = 0x01;
+ partial[sizeof(partial) - 1] ^= 0x80;
+
+ input_block_final(&bctx, partial);
+}
+
+static void do_header(norx32_ctx *ctx, const uint8_t *buf, size_t nbuf)
+{
+ if (nbuf)
+ {
+ switch_domain(ctx, DOMAIN_HEADER);
+ input(ctx, DOMAIN_HEADER, buf, nbuf);
+ }
+}
+
+static void do_trailer(norx32_ctx *ctx, const uint8_t *buf, size_t nbuf)
+{
+ if (nbuf)
+ {
+ switch_domain(ctx, DOMAIN_TRAILER);
+ input(ctx, DOMAIN_TRAILER, buf, nbuf);
+ }
+}
+
+static void body_block_encrypt(norx32_ctx *ctx,
+ const uint8_t plain[RATE_BYTES],
+ uint8_t cipher[RATE_BYTES])
+{
+ for (int i = 0; i < RATE_WORDS; i++)
+ {
+ ctx->s[i] ^= read32_le(plain);
+ write32_le(ctx->s[i], cipher);
+ plain += WORD_BYTES;
+ cipher += WORD_BYTES;
+ }
+}
+
+static void encrypt_body(norx32_ctx *ctx,
+ const uint8_t *plain, uint8_t *cipher, size_t nbytes)
+{
+ if (nbytes == 0)
+ return;
+
+ /* Process full blocks: easy */
+ while (nbytes >= RATE_BYTES)
+ {
+ switch_domain(ctx, DOMAIN_PAYLOAD);
+ body_block_encrypt(ctx, plain, cipher);
+ plain += RATE_BYTES;
+ cipher += RATE_BYTES;
+ nbytes -= RATE_BYTES;
+ }
+
+ /* Final padded block. */
+ uint8_t partial[RATE_BYTES];
+ memset(partial, 0, sizeof partial);
+ memcpy(partial, plain, nbytes);
+ partial[nbytes] ^= 0x01;
+ partial[sizeof(partial) - 1] ^= 0x80;
+
+ switch_domain(ctx, DOMAIN_PAYLOAD);
+ body_block_encrypt(ctx, partial, partial);
+
+ memcpy(cipher, partial, nbytes);
+}
+
+static void body_block_decrypt(norx32_ctx *ctx,
+ const uint8_t cipher[RATE_BYTES],
+ uint8_t plain[RATE_BYTES],
+ size_t start, size_t end)
+{
+ for (size_t i = start; i < end; i++)
+ {
+ uint32_t ct = read32_le(cipher);
+ write32_le(ctx->s[i] ^ ct, plain);
+ ctx->s[i] = ct;
+ plain += WORD_BYTES;
+ cipher += WORD_BYTES;
+ }
+}
+
+static void undo_padding(norx32_ctx *ctx, size_t bytes)
+{
+ assert(bytes < RATE_BYTES);
+ ctx->s[bytes / WORD_BYTES] ^= 0x01 << ((bytes % WORD_BYTES) * 8);
+ ctx->s[RATE_WORDS - 1] ^= 0x80000000;
+}
+
+static void decrypt_body(norx32_ctx *ctx,
+ const uint8_t *cipher, uint8_t *plain, size_t nbytes)
+{
+ if (nbytes == 0)
+ return;
+
+ /* Process full blocks. */
+ while (nbytes >= RATE_BYTES)
+ {
+ switch_domain(ctx, DOMAIN_PAYLOAD);
+ body_block_decrypt(ctx, cipher, plain, 0, RATE_WORDS);
+ plain += RATE_BYTES;
+ cipher += RATE_BYTES;
+ nbytes -= RATE_BYTES;
+ }
+
+ /* Then partial blocks. */
+ size_t offset = 0;
+ switch_domain(ctx, DOMAIN_PAYLOAD);
+
+ undo_padding(ctx, nbytes);
+
+ /* In units of whole words. */
+ while (nbytes >= WORD_BYTES)
+ {
+ body_block_decrypt(ctx, cipher, plain, offset, offset + 1);
+ plain += WORD_BYTES;
+ cipher += WORD_BYTES;
+ nbytes -= WORD_BYTES;
+ offset += 1;
+ }
+
+ /* And then, finally, bytewise. */
+ uint8_t tmp[WORD_BYTES];
+ write32_le(ctx->s[offset], tmp);
+
+ for (size_t i = 0; i < nbytes; i++)
+ {
+ uint8_t c = cipher[i];
+ plain[i] = tmp[i] ^ c;
+ tmp[i] = c;
+ }
+
+ ctx->s[offset] = read32_le(tmp);
+}
+
+static void get_tag(norx32_ctx *ctx, uint8_t tag[16])
+{
+ switch_domain(ctx, DOMAIN_TAG);
+ permute(ctx);
+ write32_le(ctx->s[0], tag + 0);
+ write32_le(ctx->s[1], tag + 4);
+ write32_le(ctx->s[2], tag + 8);
+ write32_le(ctx->s[3], tag + 12);
+}
+
+void cf_norx32_encrypt(const uint8_t key[16],
+ const uint8_t nonce[8],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *plaintext, size_t nbytes,
+ const uint8_t *trailer, size_t ntrailer,
+ uint8_t *ciphertext,
+ uint8_t tag[16])
+{
+ norx32_ctx ctx;
+
+ init(&ctx, key, nonce);
+ do_header(&ctx, header, nheader);
+ encrypt_body(&ctx, plaintext, ciphertext, nbytes);
+ do_trailer(&ctx, trailer, ntrailer);
+ get_tag(&ctx, tag);
+
+ mem_clean(&ctx, sizeof ctx);
+}
+
+int cf_norx32_decrypt(const uint8_t key[16],
+ const uint8_t nonce[8],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *ciphertext, size_t nbytes,
+ const uint8_t *trailer, size_t ntrailer,
+ const uint8_t tag[16],
+ uint8_t *plaintext)
+{
+ norx32_ctx ctx;
+ uint8_t ourtag[16];
+
+ init(&ctx, key, nonce);
+ do_header(&ctx, header, nheader);
+ decrypt_body(&ctx, ciphertext, plaintext, nbytes);
+ do_trailer(&ctx, trailer, ntrailer);
+ get_tag(&ctx, ourtag);
+
+ int err = 0;
+
+ if (!mem_eq(ourtag, tag, sizeof ourtag))
+ {
+ err = 1;
+ mem_clean(plaintext, nbytes);
+ mem_clean(ourtag, sizeof ourtag);
+ }
+
+ mem_clean(&ctx, sizeof ctx);
+ return err;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.h
new file mode 100644
index 00000000..aee7bfe1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/norx.h
@@ -0,0 +1,84 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef NORX_H
+#define NORX_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/**
+ * The NORX AEAD cipher
+ * ====================
+ * This is an implementation of NORX32-4-1 with a one-shot
+ * interface. NORX is a CAESAR candidate with a core similar
+ * to ChaCha20 and a sponge structure like Keccak.
+ *
+ * This is NORX v2.0. It is not compatible with earlier
+ * versions.
+ *
+ * NORX32 uses a 128-bit key. Each encryption requires a
+ * 64-bit nonce. An encryption processes one sequence of
+ * additional data ('header'), followed by encryption of
+ * the plaintext, followed by processing a second sequence
+ * of additional data ('trailer'). It outputs a 128-bit
+ * tag.
+ */
+
+/* .. c:function:: $DECL
+ * NORX32-4-1 one-shot encryption interface.
+ *
+ * :param key: key material.
+ * :param nonce: per-message nonce.
+ * :param header: header buffer.
+ * :param nheader: number of header bytes.
+ * :param plaintext: plaintext bytes to be encrypted.
+ * :param nbytes: number of plaintext/ciphertext bytes.
+ * :param trailer: trailer buffer.
+ * :param ntrailer: number of trailer bytes.
+ * :param ciphertext: ciphertext output buffer, nbytes in length.
+ * :param tag: authentication tag output buffer.
+ */
+void cf_norx32_encrypt(const uint8_t key[16],
+ const uint8_t nonce[8],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *plaintext, size_t nbytes,
+ const uint8_t *trailer, size_t ntrailer,
+ uint8_t *ciphertext,
+ uint8_t tag[16]);
+/* .. c:function:: $DECL
+ * NORX32-4-1 one-shot decryption interface.
+ *
+ * :return: 0 on success, non-zero on error. Plaintext is zeroed on error.
+ *
+ * :param key: key material.
+ * :param nonce: per-message nonce.
+ * :param header: header buffer.
+ * :param nheader: number of header bytes.
+ * :param ciphertext: ciphertext bytes to be decrypted.
+ * :param nbytes: number of plaintext/ciphertext bytes.
+ * :param trailer: trailer buffer.
+ * :param ntrailer: number of trailer bytes.
+ * :param plaintext: plaintext output buffer, nbytes in length.
+ * :param tag: authentication tag output buffer.
+ */
+int cf_norx32_decrypt(const uint8_t key[16],
+ const uint8_t nonce[8],
+ const uint8_t *header, size_t nheader,
+ const uint8_t *ciphertext, size_t nbytes,
+ const uint8_t *trailer, size_t ntrailer,
+ const uint8_t tag[16],
+ uint8_t *plaintext);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ocb.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ocb.c
new file mode 100644
index 00000000..3d244d4e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/ocb.c
@@ -0,0 +1,404 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "handy.h"
+#include "prp.h"
+#include "modes.h"
+#include "blockwise.h"
+#include "bitops.h"
+#include "gf128.h"
+#include "tassert.h"
+
+#include <string.h>
+
+/* How many L_n values to compute at schedule time. */
+#define MAX_L 4
+
+/* We and RFC7253 assume 128-bit blocks. */
+#define BLOCK 16
+
+typedef struct
+{
+ const cf_prp *prp;
+ void *prpctx; /* Our PRP */
+ uint8_t *out; /* Output pointer for block processing */
+ cf_gf128 L_star; /* Zero block ciphertext */
+ cf_gf128 L_dollar; /* L_$ is double of L_* */
+ cf_gf128 L[MAX_L]; /* L[0] is double of L_$, L[1] is double of L[0], etc. */
+ cf_gf128 offset; /* Offset_i */
+ cf_gf128 checksum; /* Checksum_i */
+ uint32_t i; /* Block index, 1-based */
+} ocb;
+
+typedef struct
+{
+ ocb *o; /* OCB context (contains PRP, etc.) */
+ cf_gf128 sum; /* Current Sum_i */
+ cf_gf128 offset; /* Current Offset_i */
+ uint32_t i; /* Block index, 1-based */
+} ocb_hash;
+
+static void ocb_init(ocb *o, const cf_prp *prp, void *prpctx,
+ const uint8_t *nonce, size_t nnonce,
+ size_t ntag)
+{
+ o->prp = prp;
+ o->prpctx = prpctx;
+
+ assert(o->prp->blocksz == BLOCK);
+
+ /* L_* = ENCIPHER(K, zeros(128)) */
+ uint8_t L_star_bytes[BLOCK] = { 0 };
+ prp->encrypt(prpctx, L_star_bytes, L_star_bytes);
+ cf_gf128_frombytes_be(L_star_bytes, o->L_star);
+
+ /* L_$ = double(L_*) */
+ cf_gf128_double(o->L_star, o->L_dollar);
+
+ /* L_0 = double(L_$) etc. */
+ cf_gf128_double(o->L_dollar, o->L[0]);
+
+ for (int i = 1; i < MAX_L; i++)
+ cf_gf128_double(o->L[i - 1], o->L[i]);
+
+ /* Compute nonce-dependent and per-encryption vars */
+ assert(nnonce > 0 && nnonce < BLOCK);
+ uint8_t full_nonce[BLOCK] = { 0 };
+ full_nonce[0] = ((ntag * 8) & 0x7f) << 1;
+ full_nonce[BLOCK - 1 - nnonce] |= 0x01;
+ memcpy(full_nonce + BLOCK - nnonce, nonce, nnonce);
+ uint8_t bottom = full_nonce[BLOCK - 1] & 0x3f;
+
+ /* Make Ktop */
+ full_nonce[BLOCK - 1] &= 0xc0;
+ uint8_t Ktop[BLOCK + 8];
+ prp->encrypt(prpctx, full_nonce, Ktop);
+
+ /* Stretch Ktop */
+ for (int i = 0; i < 8; i++)
+ Ktop[i + BLOCK] = Ktop[i] ^ Ktop[i + 1];
+
+ /* Outputs */
+ uint8_t offset[BLOCK];
+ copy_bytes_unaligned(offset, Ktop, BLOCK, bottom);
+ cf_gf128_frombytes_be(offset, o->offset);
+ memset(o->checksum, 0, sizeof o->checksum);
+}
+
+static void ocb_start_cipher(ocb *o, uint8_t *output)
+{
+ o->i = 1;
+ o->out = output;
+}
+
+static void ocb_add_Ln(ocb *o, uint32_t n, cf_gf128 out)
+{
+ /* Do we have a precomputed L term? */
+ if (n < MAX_L)
+ {
+ cf_gf128_add(o->L[n], out, out);
+ return;
+ }
+
+ /* Compute more terms of L. */
+ cf_gf128 accum;
+ memcpy(accum, o->L[MAX_L - 1], sizeof accum);
+
+ for (uint32_t i = MAX_L - 1; i < n; i++)
+ {
+ cf_gf128 next;
+ cf_gf128_double(accum, next);
+ memcpy(accum, next, sizeof accum);
+ }
+
+ cf_gf128_add(accum, out, out);
+}
+
+static void ocb_hash_init(ocb_hash *h)
+{
+ memset(h->offset, 0, sizeof h->offset);
+ memset(h->sum, 0, sizeof h->sum);
+ h->i = 1;
+}
+
+static void ocb_hash_sum(ocb *o, const uint8_t *block,
+ cf_gf128 sum, const cf_gf128 offset)
+{
+ uint8_t offset_bytes[BLOCK];
+ cf_gf128_tobytes_be(offset, offset_bytes);
+
+ uint8_t block_tmp[BLOCK];
+ xor_bb(block_tmp, block, offset_bytes, sizeof block_tmp);
+ o->prp->encrypt(o->prpctx, block_tmp, block_tmp);
+
+ cf_gf128 tmp;
+ cf_gf128_frombytes_be(block_tmp, tmp);
+ cf_gf128_add(sum, tmp, sum);
+}
+
+static void ocb_hash_block(void *vctx, const uint8_t *block)
+{
+ ocb_hash *h = vctx;
+
+ /* Offset_i = Offset_{i - 1} xor L{ntz(i)} */
+ ocb_add_Ln(h->o, count_trailing_zeroes(h->i), h->offset);
+
+ /* Sum_i = Sum_{i - 1} xor ENCIPHER(K, A_i xor Offset_i) */
+ ocb_hash_sum(h->o, block, h->sum, h->offset);
+
+ h->i++;
+}
+
+static void ocb_process_header(ocb *o, const uint8_t *header, size_t nheader,
+ uint8_t out[BLOCK])
+{
+ ocb_hash ctx = { o };
+ ocb_hash_init(&ctx);
+
+ uint8_t partial[BLOCK];
+ size_t npartial = 0;
+
+ cf_blockwise_accumulate(partial, &npartial,
+ o->prp->blocksz,
+ header, nheader,
+ ocb_hash_block,
+ &ctx);
+
+ if (npartial)
+ {
+ /* Offset_* = Offset_m xor L_* */
+ cf_gf128_add(ctx.offset, o->L_star, ctx.offset);
+
+ /* CipherInput = (A_* || 1 || zeros(127 - bitlen(A_*))) xor Offset_* */
+ memset(partial + npartial, 0, sizeof(partial) - npartial);
+ partial[npartial] = 0x80;
+
+ /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */
+ ocb_hash_sum(ctx.o, partial, ctx.sum, ctx.offset);
+ }
+
+ cf_gf128_tobytes_be(ctx.sum, out);
+ mem_clean(&ctx, sizeof ctx);
+}
+
+static void ocb_encrypt_block(void *vctx, const uint8_t *block)
+{
+ ocb *o = vctx;
+
+ /* Offset_i = Offset_{i - 1} xor L{ntz(i)} */
+ ocb_add_Ln(o, count_trailing_zeroes(o->i), o->offset);
+
+ /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
+ uint8_t offset_bytes[BLOCK];
+ cf_gf128_tobytes_be(o->offset, offset_bytes);
+
+ uint8_t block_tmp[BLOCK];
+ xor_bb(block_tmp, block, offset_bytes, sizeof block_tmp);
+ o->prp->encrypt(o->prpctx, block_tmp, block_tmp);
+ xor_bb(o->out, block_tmp, offset_bytes, sizeof block_tmp);
+ o->out += sizeof block_tmp;
+
+ /* Checksum_i = Checksum_{i - 1} xor P_i */
+ cf_gf128 P;
+ cf_gf128_frombytes_be(block, P);
+ cf_gf128_add(o->checksum, P, o->checksum);
+
+ o->i++;
+}
+
+void cf_ocb_encrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *plain, size_t nplain,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ uint8_t *cipher, /* the same size as nplain */
+ uint8_t *tag, size_t ntag)
+{
+ ocb o;
+ ocb_init(&o, prp, prpctx, nonce, nnonce, ntag);
+
+ /* Process blocks. The blockwise machinery takes care of
+ * splitting the input into 128-bit blocks, and calling
+ * a function on each one. */
+ uint8_t partial[BLOCK];
+ size_t npartial = 0;
+
+ ocb_start_cipher(&o, cipher);
+ cf_blockwise_accumulate(partial, &npartial,
+ prp->blocksz,
+ plain, nplain,
+ ocb_encrypt_block,
+ &o);
+
+ /* Move along plain and cipher. */
+ plain += (o.out - cipher);
+ cipher = o.out;
+
+ /* If we have remaining data to pad and process,
+ * it's in partial. */
+ if (npartial)
+ {
+ /* Offset_* = Offset_m xor L_* */
+ cf_gf128_add(o.offset, o.L_star, o.offset);
+
+ /* Pad = ENCIPHER(K, Offset_*) */
+ uint8_t pad[BLOCK];
+ cf_gf128_tobytes_be(o.offset, pad);
+ o.prp->encrypt(o.prpctx, pad, pad);
+
+ /* C_* = P_* xor Pad[1..bitlen(P_*)] */
+ xor_bb(cipher, partial, pad, npartial);
+ mem_clean(pad, sizeof pad);
+
+ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127 - bitlen(P_*))) */
+ memset(partial + npartial, 0, sizeof(partial) - npartial);
+ partial[npartial] = 0x80;
+
+ cf_gf128 last_block;
+ cf_gf128_frombytes_be(partial, last_block);
+ cf_gf128_add(o.checksum, last_block, o.checksum);
+ mem_clean(last_block, sizeof last_block);
+ }
+
+ /* Compute: Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K, A) */
+ cf_gf128 full_tag;
+ for (size_t i = 0; i < 4; i++)
+ full_tag[i] = o.checksum[i] ^ o.offset[i] ^ o.L_dollar[i];
+
+ /* Convert tag to bytes for encryption */
+ uint8_t tag_bytes[BLOCK];
+ cf_gf128_tobytes_be(full_tag, tag_bytes);
+
+ /* ENCIPHER(...) */
+ o.prp->encrypt(o.prpctx, tag_bytes, tag_bytes);
+
+ /* Compute HASH(K, A). */
+ uint8_t hash_a[BLOCK];
+ ocb_process_header(&o, header, nheader, hash_a);
+
+ /* ... xor HASH(K, A) */
+ xor_bb(tag_bytes, tag_bytes, hash_a, sizeof tag_bytes);
+
+ /* Copy out tag to caller. */
+ memcpy(tag, tag_bytes, ntag);
+
+ mem_clean(&o, sizeof o);
+}
+
+static void ocb_decrypt_block(void *vctx, const uint8_t *block)
+{
+ ocb *o = vctx;
+
+ /* Offset_i = Offset_{i - 1} xor L{ntz(i)} */
+ ocb_add_Ln(o, count_trailing_zeroes(o->i), o->offset);
+
+ /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
+ uint8_t offset_bytes[BLOCK];
+ cf_gf128_tobytes_be(o->offset, offset_bytes);
+
+ uint8_t block_tmp[BLOCK];
+ xor_bb(block_tmp, block, offset_bytes, sizeof block_tmp);
+ o->prp->decrypt(o->prpctx, block_tmp, block_tmp);
+ xor_bb(o->out, block_tmp, offset_bytes, sizeof block_tmp);
+
+ /* Checksum_i = Checksum_{i - 1} xor P_i */
+ cf_gf128 P;
+ cf_gf128_frombytes_be(o->out, P);
+ o->out += sizeof block_tmp;
+ cf_gf128_add(o->checksum, P, o->checksum);
+
+ o->i++;
+}
+
+int cf_ocb_decrypt(const cf_prp *prp, void *prpctx,
+ const uint8_t *cipher, size_t ncipher,
+ const uint8_t *header, size_t nheader,
+ const uint8_t *nonce, size_t nnonce,
+ const uint8_t *tag, size_t ntag,
+ uint8_t *plain)
+{
+ ocb o;
+ ocb_init(&o, prp, prpctx, nonce, nnonce, ntag);
+
+ /* Do blockwise decryption */
+ uint8_t partial[BLOCK];
+ size_t npartial = 0;
+
+ ocb_start_cipher(&o, plain);
+ cf_blockwise_accumulate(partial, &npartial,
+ prp->blocksz,
+ cipher, ncipher,
+ ocb_decrypt_block,
+ &o);
+
+ if (npartial)
+ {
+ /* Offset_* = Offset_m xor L_* */
+ cf_gf128_add(o.offset, o.L_star, o.offset);
+
+ /* Pad = ENCIPHER(K, Offset_*) */
+ uint8_t pad[BLOCK];
+ cf_gf128_tobytes_be(o.offset, pad);
+ o.prp->encrypt(o.prpctx, pad, pad);
+
+ /* P_* = C_* xor Pad[1..bitlen(C_*)] */
+ xor_bb(partial, partial, pad, npartial);
+ mem_clean(pad, sizeof pad);
+
+ memcpy(o.out, partial, npartial);
+
+ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127 - bitlen(P_*))) */
+ memset(partial + npartial, 0, sizeof(partial) - npartial);
+ partial[npartial] = 0x80;
+
+ cf_gf128 last_block;
+ cf_gf128_frombytes_be(partial, last_block);
+ cf_gf128_add(o.checksum, last_block, o.checksum);
+ mem_clean(last_block, sizeof last_block);
+ }
+
+ /* Compute: Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K, A) */
+ cf_gf128 full_tag;
+ for (size_t i = 0; i < 4; i++)
+ full_tag[i] = o.checksum[i] ^ o.offset[i] ^ o.L_dollar[i];
+
+ /* Convert tag to bytes for encryption */
+ uint8_t tag_bytes[BLOCK];
+ cf_gf128_tobytes_be(full_tag, tag_bytes);
+
+ /* ENCIPHER(...) */
+ o.prp->encrypt(o.prpctx, tag_bytes, tag_bytes);
+
+ /* Compute HASH(K, A). */
+ uint8_t hash_a[BLOCK];
+ ocb_process_header(&o, header, nheader, hash_a);
+
+ /* ... xor HASH(K, A) */
+ xor_bb(tag_bytes, tag_bytes, hash_a, sizeof tag_bytes);
+
+ /* Check against caller's tag. */
+ int err;
+
+ if (mem_eq(tag, tag_bytes, ntag))
+ {
+ err = 0;
+ } else {
+ err = 1;
+ mem_clean(plain, ncipher);
+ }
+
+ mem_clean(&o, sizeof o);
+ mem_clean(tag_bytes, sizeof tag_bytes);
+ mem_clean(full_tag, sizeof full_tag);
+ return err;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.c
new file mode 100644
index 00000000..fce6a22f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.c
@@ -0,0 +1,84 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "pbkdf2.h"
+#include "hmac.h"
+#include "bitops.h"
+#include "handy.h"
+#include "tassert.h"
+
+#include <string.h>
+
+static void F(const cf_hmac_ctx *startctx,
+ uint32_t counter,
+ const uint8_t *salt, size_t nsalt,
+ uint32_t iterations,
+ uint8_t *out)
+{
+ uint8_t U[CF_MAXHASH];
+ size_t hashsz = startctx->hash->hashsz;
+
+ uint8_t countbuf[4];
+ write32_be(counter, countbuf);
+
+ /* First iteration:
+ * U_1 = PRF(P, S || INT_32_BE(i))
+ */
+ cf_hmac_ctx ctx = *startctx;
+ cf_hmac_update(&ctx, salt, nsalt);
+ cf_hmac_update(&ctx, countbuf, sizeof countbuf);
+ cf_hmac_finish(&ctx, U);
+ memcpy(out, U, hashsz);
+
+ /* Subsequent iterations:
+ * U_c = PRF(P, U_{c-1})
+ */
+ for (uint32_t i = 1; i < iterations; i++)
+ {
+ ctx = *startctx;
+ cf_hmac_update(&ctx, U, hashsz);
+ cf_hmac_finish(&ctx, U);
+ xor_bb(out, out, U, hashsz);
+ }
+}
+
+void cf_pbkdf2_hmac(const uint8_t *pw, size_t npw,
+ const uint8_t *salt, size_t nsalt,
+ uint32_t iterations,
+ uint8_t *out, size_t nout,
+ const cf_chash *hash)
+{
+ uint32_t counter = 1;
+ uint8_t block[CF_MAXHASH];
+
+ assert(iterations);
+ assert(out && nout);
+ assert(hash);
+
+ /* Starting point for inner loop. */
+ cf_hmac_ctx ctx;
+ cf_hmac_init(&ctx, hash, pw, npw);
+
+ while (nout)
+ {
+ F(&ctx, counter, salt, nsalt, iterations, block);
+
+ size_t taken = MIN(nout, hash->hashsz);
+ memcpy(out, block, taken);
+ out += taken;
+ nout -= taken;
+ counter++;
+ }
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.h
new file mode 100644
index 00000000..2f304840
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/pbkdf2.h
@@ -0,0 +1,47 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef PBKDF2_H
+#define PBKDF2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "chash.h"
+
+/**
+ * PBKDF2-HMAC
+ * ===========
+ * This is PBKDF2 as described by PKCS#5/RFC2898 with HMAC as the PRF.
+ */
+
+/* .. c:function:: $DECL
+ * This computes PBKDF2-HMAC with the given hash functon.
+ *
+ * :param pw: password input buffer.
+ * :param npw: password length.
+ * :param salt: salt input buffer.
+ * :param nsalt: salt length.
+ * :param iterations: non-zero iteration count. Tune this for performance/security tradeoff.
+ * :param out: key material output buffer. `nout` bytes are written here.
+ * :param nout: key material length.
+ * :param hash: hash function description.
+ */
+void cf_pbkdf2_hmac(const uint8_t *pw, size_t npw,
+ const uint8_t *salt, size_t nsalt,
+ uint32_t iterations,
+ uint8_t *out, size_t nout,
+ const cf_chash *hash);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.c
new file mode 100644
index 00000000..6c3f13de
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.c
@@ -0,0 +1,221 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "poly1305.h"
+#include "bitops.h"
+#include "handy.h"
+#include "blockwise.h"
+
+#include <string.h>
+#include <stdio.h>
+
+void cf_poly1305_init(cf_poly1305 *ctx,
+ const uint8_t r[16],
+ const uint8_t s[16])
+{
+ memset(ctx, 0, sizeof *ctx);
+
+ ctx->r[0] = r[0];
+ ctx->r[1] = r[1];
+ ctx->r[2] = r[2];
+ ctx->r[3] = r[3] & 0x0f;
+ ctx->r[4] = r[4] & 0xfc;
+ ctx->r[5] = r[5];
+ ctx->r[6] = r[6];
+ ctx->r[7] = r[7] & 0x0f;
+ ctx->r[8] = r[8] & 0xfc;
+ ctx->r[9] = r[9];
+ ctx->r[10] = r[10];
+ ctx->r[11] = r[11] & 0x0f;
+ ctx->r[12] = r[12] & 0xfc;
+ ctx->r[13] = r[13];
+ ctx->r[14] = r[14];
+ ctx->r[15] = r[15] & 0x0f;
+ ctx->r[16] = 0;
+
+ memcpy(ctx->s, s, 16);
+}
+
+static void poly1305_add(uint32_t h[17],
+ const uint32_t x[17])
+{
+ uint32_t carry = 0;
+ int i;
+
+ for (i = 0; i < 17; i++)
+ {
+ carry += h[i] + x[i];
+ h[i] = carry & 0xff;
+ carry >>= 8;
+ }
+}
+
+/* Minimal reduction/carry chain. */
+static void poly1305_min_reduce(uint32_t x[17])
+{
+ uint32_t carry = 0;
+ int i;
+ for (i = 0; i < 16; i++)
+ {
+ carry += x[i];
+ x[i] = carry & 0xff;
+ carry >>= 8;
+ }
+
+ /* 2 ** 130 - 5 = 0x3fffffffffffffffffffffffffffffffb
+ * ^
+ * So 2 bits of carry are put into top word.
+ * Remaining bits get multiplied by 5 and carried back
+ * into bottom */
+ carry += x[16];
+ x[16] = carry & 0x03;
+ carry = 5 * (carry >> 2);
+
+ for (i = 0; i < 16; i++)
+ {
+ carry += x[i];
+ x[i] = carry & 0xff;
+ carry >>= 8;
+ }
+
+ x[16] += carry;
+}
+
+/* This is - 2 ** 130 - 5 in twos complement. */
+static const uint32_t negative_1305[17] = {
+ 0x05, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0xfc
+};
+
+static void poly1305_full_reduce(uint32_t x[17])
+{
+ uint32_t xsub[17];
+ size_t i;
+
+ for (i = 0; i < 17; i++)
+ xsub[i] = x[i];
+
+ poly1305_add(xsub, negative_1305);
+
+ /* If x - (2 ** 130 - 5) is negative, then
+ * x didn't need reduction: we discard the results.
+ * Do this in a side-channel silent way. */
+ uint32_t negative_mask = mask_u32(xsub[16] & 0x80, 0x80);
+ uint32_t positive_mask = negative_mask ^ 0xffffffff;
+
+ for (i = 0; i < 17; i++)
+ x[i] = (x[i] & negative_mask) | (xsub[i] & positive_mask);
+}
+
+static void poly1305_mul(uint32_t x[17],
+ const uint32_t y[17])
+{
+ uint32_t r[17];
+ int i;
+
+ for (i = 0; i < 17; i++)
+ {
+ uint32_t accum = 0;
+ int j;
+
+ for (j = 0; j <= i; j++)
+ accum += x[j] * y[i - j];
+
+ /* Add in carries. These get shifted 130 bits
+ * to the right, with a combination of byte indexing
+ * and shifting (136 bits right, then 6 bits left).
+ *
+ * nb. 5 << 6 is made up of two parts:
+ * 5: reduction of 2 ** 130 leaves a multiple 5
+ * shift 6 places left
+ * 17 * 8: byte indexing shift (136 bits)
+ * 130: desired shift
+ */
+ for (j = i + 1; j < 17; j++)
+ accum += (5 << 6) * x[j] * y[i + 17 - j];
+
+ r[i] = accum;
+ }
+
+ poly1305_min_reduce(r);
+
+ for (i = 0; i < 17; i++)
+ x[i] = r[i];
+}
+
+static void poly1305_block(cf_poly1305 *ctx,
+ const uint32_t c[17])
+{
+ poly1305_add(ctx->h, c);
+ poly1305_mul(ctx->h, ctx->r);
+}
+
+static void poly1305_whole_block(void *vctx,
+ const uint8_t *buf)
+{
+ cf_poly1305 *ctx = vctx;
+ uint32_t c[17];
+ int i;
+
+ for (i = 0; i < 16; i++)
+ c[i] = buf[i];
+
+ c[16] = 1;
+ poly1305_block(ctx, c);
+}
+
+static void poly1305_last_block(cf_poly1305 *ctx)
+{
+ uint32_t c[17] = { 0 };
+ size_t i;
+
+ for (i = 0; i < ctx->npartial; i++)
+ c[i] = ctx->partial[i];
+
+ c[ctx->npartial] = 1;
+ poly1305_block(ctx, c);
+}
+
+void cf_poly1305_update(cf_poly1305 *ctx,
+ const uint8_t *buf,
+ size_t nbytes)
+{
+ cf_blockwise_accumulate(ctx->partial, &ctx->npartial,
+ sizeof ctx->partial,
+ buf, nbytes,
+ poly1305_whole_block,
+ ctx);
+}
+
+void cf_poly1305_finish(cf_poly1305 *ctx,
+ uint8_t out[16])
+{
+ if (ctx->npartial)
+ poly1305_last_block(ctx);
+
+ uint32_t s[17];
+ size_t i;
+ for (i = 0; i < 16; i++)
+ s[i] = ctx->s[i];
+ s[16] = 0;
+
+ poly1305_full_reduce(ctx->h);
+ poly1305_add(ctx->h, s);
+
+ for (i = 0; i < 16; i++)
+ out[i] = ctx->h[i];
+
+ mem_clean(ctx, sizeof *ctx);
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.h
new file mode 100644
index 00000000..b318e284
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.h
@@ -0,0 +1,91 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef POLY1305_H
+#define POLY1305_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * Poly1305
+ * ========
+ * This is an incremental interface to computing the poly1305
+ * single shot MAC.
+ *
+ * Note: construct Poly1305-AES with this by taking a 16 byte
+ * nonce and encrypting it, and then using the result as an
+ * input to this function.
+ */
+
+/* .. c:type:: cf_poly1305
+ * Poly1305 incremental interface context.
+ *
+ * .. c:member:: cf_poly1305.h
+ * Current accumulator.
+ *
+ * .. c:member:: cf_poly1305.r
+ * Block multiplier.
+ *
+ * .. c:member:: cf_poly1305.s
+ * Final XOR offset.
+ *
+ * .. c:member:: cf_poly1305.partial
+ * Unprocessed input.
+ *
+ * .. c:member:: cf_poly1305.npartial
+ * Number of bytes of unprocessed input.
+ *
+ */
+typedef struct
+{
+ uint32_t h[17];
+ uint32_t r[17];
+ uint8_t s[16];
+ uint8_t partial[16];
+ size_t npartial;
+} cf_poly1305;
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to compute a new MAC.
+ *
+ * In Poly1305-AES, `r` is the second half of the 32-byte key.
+ * `s` is a nonce encrypted under the first half of the key.
+ *
+ * :param ctx: context (written)
+ * :param r: MAC key.
+ * :param s: preprocessed nonce.
+ *
+ */
+void cf_poly1305_init(cf_poly1305 *ctx,
+ const uint8_t r[16],
+ const uint8_t s[16]);
+
+/* .. c:function:: $DECL
+ * Processes `nbytes` at `data`. Copies the data if there isn't enough to make
+ * a full block.
+ */
+void cf_poly1305_update(cf_poly1305 *ctx,
+ const uint8_t *data,
+ size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Finishes the operation, writing 16 bytes to `out`.
+ *
+ * This destroys `ctx`.
+ */
+void cf_poly1305_finish(cf_poly1305 *ctx,
+ uint8_t out[16]);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.py b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.py
new file mode 100644
index 00000000..41a1b9d8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/poly1305.py
@@ -0,0 +1,127 @@
+rs = (0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91
+,0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25
+,0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65
+,0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80)
+
+msg = (0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73
+ ,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce
+ ,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4
+ ,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a
+ ,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b
+ ,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72
+ ,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2
+ ,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38
+ ,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a
+ ,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae
+ ,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea
+ ,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda
+ ,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde
+ ,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3
+ ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6
+ ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74
+ ,0xe3,0x55,0xa5)
+
+tag = (0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5
+,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9)
+
+print len(msg)
+
+WORD = 0xffffffff
+
+def add(x, y):
+ u = 0
+ r = [0] * 17
+ for i in range(17):
+ u += (x[i] + y[i]) & WORD
+ r[i] = u & 0xff
+ u >>= 8
+ return r
+
+def reduce(x):
+ r = list(x)
+ u = 0
+
+ for i in range(16):
+ u += r[i]
+ r[i] = u & 0xff
+ u >>= 8
+ u += r[16]
+ r[16] = u & 3
+ u = 5 * (u >> 2)
+
+ for i in range(16):
+ u += r[i]
+ r[i] = u & 0xff
+ u >>= 8
+ u += r[16]
+ r[16] = u
+
+ return r
+
+def modmul(x, y):
+ r = [0] * 17
+ for i in range(17):
+ u = 0
+ for j in range(i + 1):
+ u += (x[j] * y[i - j]) & WORD
+ for j in range(i + 1, 17):
+ u += (320 * x[j] * y[i + 17 - j]) & WORD
+ r[i] = u
+ return reduce(r)
+
+def dump(why, v):
+ print '%s = %s' % (why, ' '.join('%08x' % x for x in v))
+
+def freeze(x):
+ # -2^130 - 5 in twos complement
+ negative_130_5 = (5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252)
+
+ r = add(x, negative_130_5)
+ dump('minusp', r)
+ negative = bool(x[16] >> 7)
+ if negative:
+ return r
+ else:
+ return x
+
+def poly1305(msg, rs):
+ r, s = list(rs[:16]), list(rs[16:])
+
+ r[3] &= 15
+ r[4] &= 252
+ r[7] &= 15
+ r[8] &= 252
+ r[11] &= 15
+ r[12] &= 252
+ r[15] &= 15
+ r.append(0)
+
+ h = [0] * 17
+ dump('r-init', r)
+ dump('h-init', h)
+
+ block = 0
+
+ for offs in range(0, len(msg), 16):
+ print '--- block %d ---' % block
+ block += 1
+ c = list(msg[offs:offs+16])
+ c.append(1)
+ while len(c) != 17: c.append(0)
+ dump('c', c)
+
+ h = add(h, c)
+ dump('after-add', h)
+ h = modmul(h, r)
+ dump('after-mul', h)
+
+ dump('end-block', h)
+ h = freeze(h)
+ dump('h', h)
+ s.append(0)
+ h = add(h, s)
+ dump('final', h)
+ return h[:16]
+
+r = poly1305(msg, rs)
+print repr([hex(x) for x in r])
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/prp.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/prp.h
new file mode 100644
index 00000000..1aa72588
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/prp.h
@@ -0,0 +1,64 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef PRP_H
+#define PRP_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * General block cipher description
+ * ================================
+ * This allows us to implement block cipher modes which can work
+ * with different block ciphers.
+ */
+
+/* .. c:type:: cf_prp_block
+ * Block processing function type.
+ *
+ * The `in` and `out` blocks may alias.
+ *
+ * :rtype: void
+ * :param ctx: block cipher-specific context object.
+ * :param in: input block.
+ * :param out: output block.
+ */
+typedef void (*cf_prp_block)(void *ctx, const uint8_t *in, uint8_t *out);
+
+/* .. c:type:: cf_prp
+ * Describes an PRP in a general way.
+ *
+ * .. c:member:: cf_prp.blocksz
+ * Block size in bytes. Must be no more than :c:macro:`CF_MAXBLOCK`.
+ *
+ * .. c:member:: cf_prp.encrypt
+ * Block encryption function.
+ *
+ * .. c:member:: cf_prp.decrypt
+ * Block decryption function.
+ */
+typedef struct
+{
+ size_t blocksz;
+ cf_prp_block encrypt;
+ cf_prp_block decrypt;
+} cf_prp;
+
+/* .. c:macro:: CF_MAXBLOCK
+ * The maximum block cipher blocksize we support, in bytes.
+ */
+#define CF_MAXBLOCK 16
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.c
new file mode 100644
index 00000000..34bd1562
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.c
@@ -0,0 +1,164 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "salsa20.h"
+#include "bitops.h"
+#include "blockwise.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+void cf_salsa20_core(const uint8_t key0[16],
+ const uint8_t key1[16],
+ const uint8_t nonce[16],
+ const uint8_t constant[16],
+ uint8_t out[64])
+{
+ /* unpack sequence is:
+ *
+ * c0
+ * key0
+ * c1
+ * nonce
+ * c2
+ * key1
+ * c3
+ *
+ * where c0, c1, c2, c3 = constant
+ */
+
+ uint32_t z0, z1, z2, z3, z4, z5, z6, z7,
+ z8, z9, za, zb, zc, zd, ze, zf;
+
+ uint32_t x0 = z0 = read32_le(constant + 0),
+ x1 = z1 = read32_le(key0 + 0),
+ x2 = z2 = read32_le(key0 + 4),
+ x3 = z3 = read32_le(key0 + 8),
+ x4 = z4 = read32_le(key0 + 12),
+ x5 = z5 = read32_le(constant + 4),
+ x6 = z6 = read32_le(nonce + 0),
+ x7 = z7 = read32_le(nonce + 4),
+ x8 = z8 = read32_le(nonce + 8),
+ x9 = z9 = read32_le(nonce + 12),
+ xa = za = read32_le(constant + 8),
+ xb = zb = read32_le(key1 + 0),
+ xc = zc = read32_le(key1 + 4),
+ xd = zd = read32_le(key1 + 8),
+ xe = ze = read32_le(key1 + 12),
+ xf = zf = read32_le(constant + 12);
+
+#define QUARTER(v0, v1, v2, v3) \
+ v1 ^= rotl32(v0 + v3, 7); \
+ v2 ^= rotl32(v1 + v0, 9); \
+ v3 ^= rotl32(v2 + v1, 13);\
+ v0 ^= rotl32(v3 + v2, 18)
+
+#define ROW \
+ QUARTER(z0, z1, z2, z3); \
+ QUARTER(z5, z6, z7, z4); \
+ QUARTER(za, zb, z8, z9); \
+ QUARTER(zf, zc, zd, ze)
+
+#define COLUMN\
+ QUARTER(z0, z4, z8, zc); \
+ QUARTER(z5, z9, zd, z1); \
+ QUARTER(za, ze, z2, z6); \
+ QUARTER(zf, z3, z7, zb)
+
+ for (int i = 0; i < 10; i++)
+ {
+ COLUMN;
+ ROW;
+ }
+
+ x0 += z0;
+ x1 += z1;
+ x2 += z2;
+ x3 += z3;
+ x4 += z4;
+ x5 += z5;
+ x6 += z6;
+ x7 += z7;
+ x8 += z8;
+ x9 += z9;
+ xa += za;
+ xb += zb;
+ xc += zc;
+ xd += zd;
+ xe += ze;
+ xf += zf;
+
+ write32_le(x0, out + 0);
+ write32_le(x1, out + 4);
+ write32_le(x2, out + 8);
+ write32_le(x3, out + 12);
+ write32_le(x4, out + 16);
+ write32_le(x5, out + 20);
+ write32_le(x6, out + 24);
+ write32_le(x7, out + 28);
+ write32_le(x8, out + 32);
+ write32_le(x9, out + 36);
+ write32_le(xa, out + 40);
+ write32_le(xb, out + 44);
+ write32_le(xc, out + 48);
+ write32_le(xd, out + 52);
+ write32_le(xe, out + 56);
+ write32_le(xf, out + 60);
+}
+
+static const uint8_t *salsa20_tau = (const uint8_t *) "expand 16-byte k";
+static const uint8_t *salsa20_sigma = (const uint8_t *) "expand 32-byte k";
+
+void cf_salsa20_init(cf_salsa20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8])
+{
+ switch (nkey)
+ {
+ case 16:
+ memcpy(ctx->key0, key, 16);
+ memcpy(ctx->key1, key, 16);
+ ctx->constant = salsa20_tau;
+ break;
+ case 32:
+ memcpy(ctx->key0, key, 16);
+ memcpy(ctx->key1, key + 16, 16);
+ ctx->constant = salsa20_sigma;
+ break;
+ default:
+ abort();
+ }
+
+ memset(ctx->nonce, 0, sizeof ctx->nonce);
+ memcpy(ctx->nonce + 8, nonce, 8);
+ ctx->nblock = 0;
+ ctx->ncounter = 8;
+}
+
+static void cf_salsa20_next_block(void *vctx, uint8_t *out)
+{
+ cf_salsa20_ctx *ctx = vctx;
+ cf_salsa20_core(ctx->key0,
+ ctx->key1,
+ ctx->nonce,
+ ctx->constant,
+ out);
+ incr_le(ctx->nonce, ctx->ncounter);
+}
+
+void cf_salsa20_cipher(cf_salsa20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes)
+{
+ cf_blockwise_xor(ctx->block, &ctx->nblock, 64,
+ input, output, bytes,
+ cf_salsa20_next_block,
+ ctx);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.h
new file mode 100644
index 00000000..462d0190
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/salsa20.h
@@ -0,0 +1,140 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef SALSA20_H
+#define SALSA20_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+/**
+ * The Salsa20/Chacha20 stream ciphers
+ * ===================================
+ *
+ * These are similar stream ciphers by djb.
+ *
+ * A reduced round variant of Salsa20 (Salsa20/12)
+ * was selected as a finalist of the eSTREAM stream
+ * cipher competition. This implementation does
+ * the full 20 rounds.
+ *
+ * ChaCha20 is fundamentally like Salsa20, but
+ * has a tweaked round function to improve security
+ * margin without damaging performance.
+ */
+
+/* Salsa20 core transform. */
+void cf_salsa20_core(const uint8_t key0[16],
+ const uint8_t key1[16],
+ const uint8_t nonce[16],
+ const uint8_t constant[16],
+ uint8_t out[64]);
+
+/* Chacha20 core transform. */
+void cf_chacha20_core(const uint8_t key0[16],
+ const uint8_t key1[16],
+ const uint8_t nonce[16],
+ const uint8_t constant[16],
+ uint8_t out[64]);
+
+/* .. c:type:: cf_salsa20_ctx
+ * Incremental interface to Salsa20.
+ *
+ * .. c:member:: cf_salsa20_ctx.key0
+ * Half of key material.
+ *
+ * .. c:member:: cf_salsa20_ctx.key1
+ * Half of key material.
+ *
+ * .. c:member:: cf_salsa20_ctx.nonce
+ * Nonce and counter block.
+ *
+ * .. c:member:: cf_salsa20_ctx.constant
+ * Per-key-length constants.
+ *
+ * .. c:member:: cf_salsa20_ctx.block
+ * Buffer for unused key stream material.
+ *
+ * .. c:member:: cf_salsa20_ctx.nblock
+ * Number of bytes at end of `block` that can be used as key stream.
+ *
+ */
+typedef struct
+{
+ uint8_t key0[16], key1[16];
+ uint8_t nonce[16];
+ const uint8_t *constant;
+ uint8_t block[64];
+ size_t nblock;
+ size_t ncounter;
+} cf_salsa20_ctx, cf_chacha20_ctx;
+
+/* .. c:type:: cf_chacha20_ctx
+ * Incremental interface to Chacha20. This structure
+ * is identical to :c:type:`cf_salsa20_ctx`.
+ */
+
+/* .. c:function:: $DECL
+ * Salsa20 initialisation function.
+ *
+ * :param ctx: salsa20 context.
+ * :param key: key material.
+ * :param nkey: length of key in bytes, either 16 or 32.
+ * :param nonce: per-message nonce.
+ */
+void cf_salsa20_init(cf_salsa20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]);
+
+/* .. c:function:: $DECL
+ * Chacha20 initialisation function.
+ *
+ * :param ctx: chacha20 context (written).
+ * :param key: key material.
+ * :param nkey: length of key in bytes, either 16 or 32.
+ * :param nonce: per-message nonce.
+ */
+void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]);
+
+/* .. c:function:: $DECL
+ * Chacha20 initialisation function. This version gives full control over the whole
+ * initial nonce value, and the size of the counter. The counter is always at the front
+ * of the nonce.
+ *
+ * :param ctx: chacha20 context (written).
+ * :param key: key material.
+ * :param nkey: length of key in bytes, either 16 or 32.
+ * :param nonce: per-message nonce. `ncounter` bytes at the start are the block counter.
+ * :param ncounter: length, in bytes, of the counter portion of the nonce.
+ */
+void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey,
+ const uint8_t nonce[16], size_t ncounter);
+
+/* .. c:function:: $DECL
+ * Salsa20 encryption/decryption function.
+ *
+ * :param ctx: salsa20 context.
+ * :param input: input data buffer (read), `count` bytes long.
+ * :param output: output data buffer (written), `count` bytes long.
+ */
+void cf_salsa20_cipher(cf_salsa20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t count);
+
+/* .. c:function:: $DECL
+ * Chacha20 encryption/decryption function.
+ *
+ * :param ctx: chacha20 context.
+ * :param input: input data buffer (read), `count` bytes long.
+ * :param output: output data buffer (written), `count` bytes long.
+ */
+void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t count);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.c
new file mode 100644
index 00000000..8b7d02fe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.c
@@ -0,0 +1,150 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <string.h>
+
+#include "sha1.h"
+#include "blockwise.h"
+#include "bitops.h"
+#include "handy.h"
+#include "tassert.h"
+
+void cf_sha1_init(cf_sha1_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->H[0] = 0x67452301;
+ ctx->H[1] = 0xefcdab89;
+ ctx->H[2] = 0x98badcfe;
+ ctx->H[3] = 0x10325476;
+ ctx->H[4] = 0xc3d2e1f0;
+}
+
+static void sha1_update_block(void *vctx, const uint8_t *inp)
+{
+ cf_sha1_context *ctx = vctx;
+
+ /* This is a 16-word window into the whole W array. */
+ uint32_t W[16];
+
+ uint32_t a = ctx->H[0],
+ b = ctx->H[1],
+ c = ctx->H[2],
+ d = ctx->H[3],
+ e = ctx->H[4],
+ Wt;
+
+ for (size_t t = 0; t < 80; t++)
+ {
+ /* For W[0..16] we process the input into W.
+ * For W[16..79] we compute the next W value:
+ *
+ * W[t] = (W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]) <<< 1
+ *
+ * But all W indices are reduced mod 16 into our window.
+ */
+ if (t < 16)
+ {
+ W[t] = Wt = read32_be(inp);
+ inp += 4;
+ } else {
+ Wt = W[(t - 3) % 16] ^ W[(t - 8) % 16] ^ W[(t - 14) % 16] ^ W[(t - 16) % 16];
+ Wt = rotl32(Wt, 1);
+ W[t % 16] = Wt;
+ }
+
+ uint32_t f, k;
+
+ if (t <= 19)
+ {
+ f = (b & c) | (~b & d);
+ k = 0x5a827999;
+ } else if (t <= 39) {
+ f = b ^ c ^ d;
+ k = 0x6ed9eba1;
+ } else if (t <= 59) {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8f1bbcdc;
+ } else {
+ f = b ^ c ^ d;
+ k = 0xca62c1d6;
+ }
+
+ uint32_t temp = rotl32(a, 5) + f + e + k + Wt;
+ e = d;
+ d = c;
+ c = rotl32(b, 30);
+ b = a;
+ a = temp;
+ }
+
+ ctx->H[0] += a;
+ ctx->H[1] += b;
+ ctx->H[2] += c;
+ ctx->H[3] += d;
+ ctx->H[4] += e;
+
+ ctx->blocks++;
+}
+
+void cf_sha1_update(cf_sha1_context *ctx, const void *data, size_t nbytes)
+{
+ cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial,
+ data, nbytes,
+ sha1_update_block, ctx);
+}
+
+void cf_sha1_digest(const cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ])
+{
+ cf_sha1_context ours = *ctx;
+ cf_sha1_digest_final(&ours, hash);
+}
+
+void cf_sha1_digest_final(cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ])
+{
+ uint64_t digested_bytes = ctx->blocks;
+ digested_bytes = digested_bytes * CF_SHA1_BLOCKSZ + ctx->npartial;
+ uint64_t digested_bits = digested_bytes * 8;
+
+ size_t padbytes = CF_SHA1_BLOCKSZ - ((digested_bytes + 8) % CF_SHA1_BLOCKSZ);
+
+ /* Hash 0x80 00 ... block first. */
+ cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial,
+ 0x80, 0x00, 0x00, padbytes,
+ sha1_update_block, ctx);
+
+ /* Now hash length. */
+ uint8_t buf[8];
+ write64_be(digested_bits, buf);
+ cf_sha1_update(ctx, buf, 8);
+
+ /* We ought to have got our padding calculation right! */
+ assert(ctx->npartial == 0);
+
+ write32_be(ctx->H[0], hash + 0);
+ write32_be(ctx->H[1], hash + 4);
+ write32_be(ctx->H[2], hash + 8);
+ write32_be(ctx->H[3], hash + 12);
+ write32_be(ctx->H[4], hash + 16);
+
+ memset(ctx, 0, sizeof *ctx);
+}
+
+const cf_chash cf_sha1 = {
+ .hashsz = CF_SHA1_HASHSZ,
+ .blocksz = CF_SHA1_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha1_init,
+ .update = (cf_chash_update) cf_sha1_update,
+ .digest = (cf_chash_digest) cf_sha1_digest
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.h
new file mode 100644
index 00000000..4ca0e91c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha1.h
@@ -0,0 +1,91 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef SHA1_H
+#define SHA1_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "chash.h"
+
+/**
+ * SHA1
+ * ====
+ *
+ * You shouldn't use this for anything new.
+ */
+
+/* .. c:macro:: CF_SHA1_HASHSZ
+ * The output size of SHA1: 20 bytes. */
+#define CF_SHA1_HASHSZ 20
+
+/* .. c:macro:: CF_SHA1_BLOCKSZ
+ * The block size of SHA1: 64 bytes. */
+#define CF_SHA1_BLOCKSZ 64
+
+/* .. c:type:: cf_sha1_context
+ * Incremental SHA1 hashing context.
+ *
+ * .. c:member:: cf_sha1_context.H
+ * Intermediate values.
+ *
+ * .. c:member:: cf_sha1_context.partial
+ * Unprocessed input.
+ *
+ * .. c:member:: cf_sha1_context.npartial
+ * Number of bytes of unprocessed input.
+ *
+ * .. c:member:: cf_sha1_context.blocks
+ * Number of full blocks processed.
+ */
+typedef struct
+{
+ uint32_t H[5]; /* State. */
+ uint8_t partial[CF_SHA1_BLOCKSZ]; /* Partial block of input. */
+ uint32_t blocks; /* Number of full blocks processed into H. */
+ size_t npartial; /* Number of bytes in prefix of partial. */
+} cf_sha1_context;
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to hash a new message.
+ */
+extern void cf_sha1_init(cf_sha1_context *ctx);
+
+/* .. c:function:: $DECL
+ * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make
+ * a full block.
+ */
+extern void cf_sha1_update(cf_sha1_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA1_HASHSZ` bytes to `hash`.
+ *
+ * This leaves `ctx` unchanged.
+ */
+extern void cf_sha1_digest(const cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA1_HASHSZ` bytes to `hash`.
+ *
+ * This destroys `ctx`, but uses less stack than :c:func:`cf_sha1_digest`.
+ */
+extern void cf_sha1_digest_final(cf_sha1_context *ctx, uint8_t hash[CF_SHA1_HASHSZ]);
+
+/* .. c:var:: cf_sha1
+ * Abstract interface to SHA1. See :c:type:`cf_chash` for more information.
+ */
+extern const cf_chash cf_sha1;
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha2.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha2.h
new file mode 100644
index 00000000..c4ed24b5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha2.h
@@ -0,0 +1,235 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef SHA2_H
+#define SHA2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "chash.h"
+
+/**
+ * SHA224/SHA256
+ * =============
+ */
+
+/* .. c:macro:: CF_SHA224_HASHSZ
+ * The output size of SHA224: 28 bytes. */
+#define CF_SHA224_HASHSZ 28
+
+/* .. c:macro:: CF_SHA224_BLOCKSZ
+ * The block size of SHA224: 64 bytes. */
+#define CF_SHA224_BLOCKSZ 64
+
+/* .. c:macro:: CF_SHA256_HASHSZ
+ * The output size of SHA256: 32 bytes. */
+#define CF_SHA256_HASHSZ 32
+
+/* .. c:macro:: CF_SHA256_BLOCKSZ
+ * The block size of SHA256: 64 bytes. */
+#define CF_SHA256_BLOCKSZ 64
+
+/* .. c:type:: cf_sha256_context
+ * Incremental SHA256 hashing context.
+ *
+ * .. c:member:: cf_sha256_context.H
+ * Intermediate values.
+ *
+ * .. c:member:: cf_sha256_context.partial
+ * Unprocessed input.
+ *
+ * .. c:member:: cf_sha256_context.npartial
+ * Number of bytes of unprocessed input.
+ *
+ * .. c:member:: cf_sha256_context.blocks
+ * Number of full blocks processed.
+ */
+typedef struct
+{
+ uint32_t H[8]; /* State. */
+ uint8_t partial[CF_SHA256_BLOCKSZ]; /* Partial block of input. */
+ uint32_t blocks; /* Number of full blocks processed into H. */
+ size_t npartial; /* Number of bytes in prefix of partial. */
+} cf_sha256_context;
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to hash a new message.
+ */
+extern void cf_sha256_init(cf_sha256_context *ctx);
+
+/* .. c:function:: $DECL
+ * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make
+ * a full block.
+ */
+extern void cf_sha256_update(cf_sha256_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA256_HASHSZ` bytes to `hash`.
+ *
+ * This leaves `ctx` unchanged.
+ */
+extern void cf_sha256_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA256_HASHSZ` bytes to `hash`.
+ *
+ * This destroys `ctx`, but uses less stack than :c:func:`cf_sha256_digest`.
+ */
+extern void cf_sha256_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to hash a new message.
+ *
+ * nb. SHA224 uses SHA256's underlying types.
+ */
+extern void cf_sha224_init(cf_sha256_context *ctx);
+
+/* .. c:function:: $DECL
+ * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make
+ * a full block.
+ */
+extern void cf_sha224_update(cf_sha256_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA224_HASHSZ` bytes to `hash`.
+ *
+ * This leaves `ctx` unchanged.
+ */
+extern void cf_sha224_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA224_HASHSZ` bytes to `hash`.
+ *
+ * This destroys `ctx`, but uses less stack than :c:func:`cf_sha224_digest`.
+ */
+extern void cf_sha224_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ]);
+
+/* .. c:var:: cf_sha224
+ * Abstract interface to SHA224. See :c:type:`cf_chash` for more information.
+ */
+extern const cf_chash cf_sha224;
+
+/* .. c:var:: cf_sha256
+ * Abstract interface to SHA256. See :c:type:`cf_chash` for more information.
+ */
+extern const cf_chash cf_sha256;
+
+/**
+ * SHA384/SHA512
+ * =============
+ */
+
+/* .. c:macro:: CF_SHA384_HASHSZ
+ * The output size of SHA384: 48 bytes. */
+#define CF_SHA384_HASHSZ 48
+
+/* .. c:macro:: CF_SHA384_BLOCKSZ
+ * The block size of SHA384: 128 bytes. */
+#define CF_SHA384_BLOCKSZ 128
+
+/* .. c:macro:: CF_SHA512_HASHSZ
+ * The output size of SHA512: 64 bytes. */
+#define CF_SHA512_HASHSZ 64
+
+/* .. c:macro:: CF_SHA512_BLOCKSZ
+ * The block size of SHA512: 128 bytes. */
+#define CF_SHA512_BLOCKSZ 128
+
+/* .. c:type:: cf_sha512_context
+ * Incremental SHA512 hashing context.
+ *
+ * .. c:member:: cf_sha512_context.H
+ * Intermediate values.
+ *
+ * .. c:member:: cf_sha512_context.partial
+ * Unprocessed input.
+ *
+ * .. c:member:: cf_sha512_context.npartial
+ * Number of bytes of unprocessed input.
+ *
+ * .. c:member:: cf_sha512_context.blocks
+ * Number of full blocks processed.
+ */
+typedef struct
+{
+ uint64_t H[8];
+ uint8_t partial[CF_SHA512_BLOCKSZ];
+ uint32_t blocks;
+ size_t npartial;
+} cf_sha512_context;
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to hash a new message.
+ */
+extern void cf_sha512_init(cf_sha512_context *ctx);
+
+/* .. c:function:: $DECL
+ * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make
+ * a full block.
+ */
+extern void cf_sha512_update(cf_sha512_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA512_HASHSZ` bytes to `hash`.
+ *
+ * This leaves `ctx` unchanged.
+ */
+extern void cf_sha512_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA512_HASHSZ` bytes to `hash`.
+ *
+ * This destroys `ctx`, but uses less stack than :c:func:`cf_sha512_digest`.
+ */
+extern void cf_sha512_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to hash a new message.
+ *
+ * nb. SHA384 uses SHA512's underlying types.
+ */
+extern void cf_sha384_init(cf_sha512_context *ctx);
+
+/* .. c:function:: $DECL
+ * Hashes `nbytes` at `data`. Copies the data if there isn't enough to make
+ * a full block.
+ */
+extern void cf_sha384_update(cf_sha512_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA384_HASHSZ` bytes to `hash`.
+ *
+ * This leaves `ctx` unchanged.
+ */
+extern void cf_sha384_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hash operation, writing `CF_SHA384_HASHSZ` bytes to `hash`.
+ *
+ * This destroys `ctx`, but uses less stack than :c:func:`cf_sha384_digest`.
+ */
+extern void cf_sha384_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ]);
+
+/* .. c:var:: cf_sha384
+ * Abstract interface to SHA384. See :c:type:`cf_chash` for more information.
+ */
+extern const cf_chash cf_sha384;
+
+/* .. c:var:: cf_sha512
+ * Abstract interface to SHA512. See :c:type:`cf_chash` for more information.
+ */
+extern const cf_chash cf_sha512;
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha256.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha256.c
new file mode 100644
index 00000000..8ecef168
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha256.c
@@ -0,0 +1,232 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <string.h>
+
+#include "sha2.h"
+#include "blockwise.h"
+#include "bitops.h"
+#include "handy.h"
+#include "tassert.h"
+
+static const uint32_t K[64] = {
+ 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
+};
+
+# define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
+# define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+# define BSIG0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
+# define BSIG1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
+# define SSIG0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3))
+# define SSIG1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
+
+void cf_sha256_init(cf_sha256_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->H[0] = 0x6a09e667;
+ ctx->H[1] = 0xbb67ae85;
+ ctx->H[2] = 0x3c6ef372;
+ ctx->H[3] = 0xa54ff53a;
+ ctx->H[4] = 0x510e527f;
+ ctx->H[5] = 0x9b05688c;
+ ctx->H[6] = 0x1f83d9ab;
+ ctx->H[7] = 0x5be0cd19;
+}
+
+void cf_sha224_init(cf_sha256_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->H[0] = 0xc1059ed8;
+ ctx->H[1] = 0x367cd507;
+ ctx->H[2] = 0x3070dd17;
+ ctx->H[3] = 0xf70e5939;
+ ctx->H[4] = 0xffc00b31;
+ ctx->H[5] = 0x68581511;
+ ctx->H[6] = 0x64f98fa7;
+ ctx->H[7] = 0xbefa4fa4;
+}
+
+static void sha256_update_block(void *vctx, const uint8_t *inp)
+{
+ cf_sha256_context *ctx = vctx;
+
+ /* This is a 16-word window into the whole W array. */
+ uint32_t W[16];
+
+ uint32_t a = ctx->H[0],
+ b = ctx->H[1],
+ c = ctx->H[2],
+ d = ctx->H[3],
+ e = ctx->H[4],
+ f = ctx->H[5],
+ g = ctx->H[6],
+ h = ctx->H[7],
+ Wt;
+
+ size_t t;
+ for (t = 0; t < 64; t++)
+ {
+ /* For W[0..16] we process the input into W.
+ * For W[16..64] we compute the next W value:
+ *
+ * W[t] = SSIG1(W[t - 2]) + W[t - 7] + SSIG0(W[t - 15]) + W[t - 16];
+ *
+ * But all W indices are reduced mod 16 into our window.
+ */
+ if (t < 16)
+ {
+ W[t] = Wt = read32_be(inp);
+ inp += 4;
+ } else {
+ Wt = SSIG1(W[(t - 2) % 16]) +
+ W[(t - 7) % 16] +
+ SSIG0(W[(t - 15) % 16]) +
+ W[(t - 16) % 16];
+ W[t % 16] = Wt;
+ }
+
+ uint32_t T1 = h + BSIG1(e) + CH(e, f, g) + K[t] + Wt;
+ uint32_t T2 = BSIG0(a) + MAJ(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+ }
+
+ ctx->H[0] += a;
+ ctx->H[1] += b;
+ ctx->H[2] += c;
+ ctx->H[3] += d;
+ ctx->H[4] += e;
+ ctx->H[5] += f;
+ ctx->H[6] += g;
+ ctx->H[7] += h;
+
+ ctx->blocks++;
+}
+
+void cf_sha256_update(cf_sha256_context *ctx, const void *data, size_t nbytes)
+{
+ cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial,
+ data, nbytes,
+ sha256_update_block, ctx);
+}
+
+void cf_sha224_update(cf_sha256_context *ctx, const void *data, size_t nbytes)
+{
+ cf_sha256_update(ctx, data, nbytes);
+}
+
+void cf_sha256_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ])
+{
+ /* We copy the context, so the finalisation doesn't effect the caller's
+ * context. This means the caller can do:
+ *
+ * x = init()
+ * x.update('hello')
+ * h1 = x.digest()
+ * x.update(' world')
+ * h2 = x.digest()
+ *
+ * to get h1 = H('hello') and h2 = H('hello world')
+ *
+ * This wouldn't work if we applied MD-padding to *ctx.
+ */
+
+ cf_sha256_context ours = *ctx;
+ cf_sha256_digest_final(&ours, hash);
+}
+
+void cf_sha256_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA256_HASHSZ])
+{
+ uint64_t digested_bytes = ctx->blocks;
+ digested_bytes = digested_bytes * CF_SHA256_BLOCKSZ + ctx->npartial;
+ uint64_t digested_bits = digested_bytes * 8;
+
+ size_t padbytes = CF_SHA256_BLOCKSZ - ((digested_bytes + 8) % CF_SHA256_BLOCKSZ);
+
+ /* Hash 0x80 00 ... block first. */
+ cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial,
+ 0x80, 0x00, 0x00, padbytes,
+ sha256_update_block, ctx);
+
+ /* Now hash length. */
+ uint8_t buf[8];
+ write64_be(digested_bits, buf);
+ cf_sha256_update(ctx, buf, 8);
+
+ /* We ought to have got our padding calculation right! */
+ assert(ctx->npartial == 0);
+
+ write32_be(ctx->H[0], hash + 0);
+ write32_be(ctx->H[1], hash + 4);
+ write32_be(ctx->H[2], hash + 8);
+ write32_be(ctx->H[3], hash + 12);
+ write32_be(ctx->H[4], hash + 16);
+ write32_be(ctx->H[5], hash + 20);
+ write32_be(ctx->H[6], hash + 24);
+ write32_be(ctx->H[7], hash + 28);
+
+ memset(ctx, 0, sizeof *ctx);
+}
+
+void cf_sha224_digest(const cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ])
+{
+ uint8_t full[CF_SHA256_HASHSZ];
+ cf_sha256_digest(ctx, full);
+ memcpy(hash, full, CF_SHA224_HASHSZ);
+}
+
+void cf_sha224_digest_final(cf_sha256_context *ctx, uint8_t hash[CF_SHA224_HASHSZ])
+{
+ uint8_t full[CF_SHA256_HASHSZ];
+ cf_sha256_digest_final(ctx, full);
+ memcpy(hash, full, CF_SHA224_HASHSZ);
+}
+
+const cf_chash cf_sha224 = {
+ .hashsz = CF_SHA224_HASHSZ,
+ .blocksz = CF_SHA256_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha224_init,
+ .update = (cf_chash_update) cf_sha224_update,
+ .digest = (cf_chash_digest) cf_sha224_digest
+};
+
+const cf_chash cf_sha256 = {
+ .hashsz = CF_SHA256_HASHSZ,
+ .blocksz = CF_SHA256_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha256_init,
+ .update = (cf_chash_update) cf_sha256_update,
+ .digest = (cf_chash_digest) cf_sha256_digest
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.c
new file mode 100644
index 00000000..f130747d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.c
@@ -0,0 +1,444 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <string.h>
+
+#include "sha3.h"
+#include "blockwise.h"
+#include "handy.h"
+#include "bitops.h"
+#include "tassert.h"
+
+/* The round constants, pre-interleaved. See bitinter.py */
+static const cf_sha3_bi round_constants[24] = {
+ { 0x00000001, 0x00000000 }, { 0x00000000, 0x00000089 },
+ { 0x00000000, 0x8000008b }, { 0x00000000, 0x80008080 },
+ { 0x00000001, 0x0000008b }, { 0x00000001, 0x00008000 },
+ { 0x00000001, 0x80008088 }, { 0x00000001, 0x80000082 },
+ { 0x00000000, 0x0000000b }, { 0x00000000, 0x0000000a },
+ { 0x00000001, 0x00008082 }, { 0x00000000, 0x00008003 },
+ { 0x00000001, 0x0000808b }, { 0x00000001, 0x8000000b },
+ { 0x00000001, 0x8000008a }, { 0x00000001, 0x80000081 },
+ { 0x00000000, 0x80000081 }, { 0x00000000, 0x80000008 },
+ { 0x00000000, 0x00000083 }, { 0x00000000, 0x80008003 },
+ { 0x00000001, 0x80008088 }, { 0x00000000, 0x80000088 },
+ { 0x00000001, 0x00008000 }, { 0x00000000, 0x80008082 }
+};
+
+static const uint8_t rotation_constants[5][5] = {
+ { 0, 1, 62, 28, 27, },
+ { 36, 44, 6, 55, 20, },
+ { 3, 10, 43, 25, 39, },
+ { 41, 45, 15, 21, 8, },
+ { 18, 2, 61, 56, 14, }
+};
+
+/* --- Bit interleaving and uninterleaving --- */
+/* See bitinter.py for models of these bit twiddles. The originals
+ * come from "Hacker's Delight" by Henry Warren, where they are named
+ * shuffle2 and unshuffle.
+ * See:
+ * http://www.hackersdelight.org/hdcodetxt/shuffle.c.txt
+ *
+ * The overriding aim is to change bit ordering:
+ * AaBbCcDd -> ABCDabcd
+ * and back. Once they're in the shuffled form, we can extract
+ * odd/even bits by taking the half words from each pair.
+ */
+
+static inline uint32_t shuffle_out(uint32_t x)
+{
+ uint32_t t;
+ t = (x ^ (x >> 1)) & 0x22222222; x = x ^ t ^ (t << 1);
+ t = (x ^ (x >> 2)) & 0x0c0c0c0c; x = x ^ t ^ (t << 2);
+ t = (x ^ (x >> 4)) & 0x00f000f0; x = x ^ t ^ (t << 4);
+ t = (x ^ (x >> 8)) & 0x0000ff00; x = x ^ t ^ (t << 8);
+ return x;
+}
+
+/* Convert ABCDabcd -> AaBbCcDd. */
+static inline uint32_t shuffle_in(uint32_t x)
+{
+ uint32_t t;
+ t = (x ^ (x >> 8)) & 0x0000ff00; x = x ^ t ^ (t << 8);
+ t = (x ^ (x >> 4)) & 0x00f000f0; x = x ^ t ^ (t << 4);
+ t = (x ^ (x >> 2)) & 0x0c0c0c0c; x = x ^ t ^ (t << 2);
+ t = (x ^ (x >> 1)) & 0x22222222; x = x ^ t ^ (t << 1);
+ return x;
+}
+
+static inline void read64_bi(cf_sha3_bi *out, const uint8_t data[8])
+{
+ uint32_t lo = read32_le(data + 0),
+ hi = read32_le(data + 4);
+
+ lo = shuffle_out(lo);
+ hi = shuffle_out(hi);
+
+ out->odd = (lo & 0x0000ffff) | (hi << 16);
+ out->evn = (lo >> 16) | (hi & 0xffff0000);
+}
+
+static inline void write64_bi(const cf_sha3_bi *bi, uint8_t data[8])
+{
+ uint32_t lo = (bi->odd & 0x0000ffff) | (bi->evn << 16),
+ hi = (bi->odd >> 16) | (bi->evn & 0xffff0000);
+
+ lo = shuffle_in(lo);
+ hi = shuffle_in(hi);
+
+ write32_le(lo, data + 0);
+ write32_le(hi, data + 4);
+}
+
+static inline void rotl_bi_1(cf_sha3_bi *out, const cf_sha3_bi *in)
+{
+ /* in bit-interleaved representation, a rotation of 1
+ * is a swap plus a single rotation of the odd word. */
+ out->odd = rotl32(in->evn, 1);
+ out->evn = in->odd;
+}
+
+static inline void rotl_bi_n(cf_sha3_bi *out, const cf_sha3_bi *in, uint8_t rot)
+{
+ uint8_t half = rot >> 1;
+
+ /* nb. rot is a constant, so this isn't a branch leak. */
+ if (rot & 1)
+ {
+ out->odd = rotl32(in->evn, half + 1);
+ out->evn = rotl32(in->odd, half);
+ } else {
+ out->evn = rotl32(in->evn, half);
+ out->odd = rotl32(in->odd, half);
+ }
+}
+
+/* --- */
+
+static void sha3_init(cf_sha3_context *ctx, uint16_t rate_bits, uint16_t capacity_bits)
+{
+ mem_clean(ctx, sizeof *ctx);
+ ctx->rate = rate_bits / 8;
+ ctx->capacity = capacity_bits / 8;
+}
+
+static void absorb(cf_sha3_context *ctx, const uint8_t *data, uint16_t sz)
+{
+ uint16_t lanes = sz / 8;
+
+ for (uint16_t x = 0, y = 0, i = 0; i < lanes; i++)
+ {
+ cf_sha3_bi bi;
+ read64_bi(&bi, data);
+ ctx->A[x][y].odd ^= bi.odd;
+ ctx->A[x][y].evn ^= bi.evn;
+ data += 8;
+
+ x++;
+ if (x == 5)
+ {
+ y++;
+ x = 0;
+ }
+ }
+}
+
+/* Integers [-1,20] mod 5. To avoid a divmod. Indices
+ * are constants; not data-dependant. */
+static const uint8_t mod5_table[] = {
+ 4,
+ 0,
+ 1, 2, 3, 4, 0, 1, 2, 3, 4, 0,
+ 1, 2, 3, 4, 0, 1, 2, 3, 4, 0
+};
+
+#define MOD5(x) (mod5_table[(x) + 1])
+
+static void theta(cf_sha3_context *ctx)
+{
+ cf_sha3_bi C[5], D[5];
+
+ for (int x = 0; x < 5; x++)
+ {
+ C[x].odd = ctx->A[x][0].odd ^ ctx->A[x][1].odd ^ ctx->A[x][2].odd ^ ctx->A[x][3].odd ^ ctx->A[x][4].odd;
+ C[x].evn = ctx->A[x][0].evn ^ ctx->A[x][1].evn ^ ctx->A[x][2].evn ^ ctx->A[x][3].evn ^ ctx->A[x][4].evn;
+ }
+
+ for (int x = 0; x < 5; x++)
+ {
+ cf_sha3_bi r;
+ rotl_bi_1(&r, &C[MOD5(x + 1)]);
+ D[x].odd = C[MOD5(x - 1)].odd ^ r.odd;
+ D[x].evn = C[MOD5(x - 1)].evn ^ r.evn;
+
+ for (int y = 0; y < 5; y++)
+ {
+ ctx->A[x][y].odd ^= D[x].odd;
+ ctx->A[x][y].evn ^= D[x].evn;
+ }
+ }
+}
+
+static void rho_pi_chi(cf_sha3_context *ctx)
+{
+ cf_sha3_bi B[5][5] = { { { 0 } } };
+
+ for (int x = 0; x < 5; x++)
+ for (int y = 0; y < 5; y++)
+ rotl_bi_n(&B[y][MOD5(2 * x + 3 * y)], &ctx->A[x][y], rotation_constants[y][x]);
+
+ for (int x = 0; x < 5; x++)
+ {
+ unsigned x1 = MOD5(x + 1);
+ unsigned x2 = MOD5(x + 2);
+
+ for (int y = 0; y < 5; y++)
+ {
+ ctx->A[x][y].odd = B[x][y].odd ^ ((~ B[x1][y].odd) & B[x2][y].odd);
+ ctx->A[x][y].evn = B[x][y].evn ^ ((~ B[x1][y].evn) & B[x2][y].evn);
+ }
+ }
+}
+
+static void permute(cf_sha3_context *ctx)
+{
+ for (int r = 0; r < 24; r++)
+ {
+ theta(ctx);
+ rho_pi_chi(ctx);
+
+ /* iota */
+ ctx->A[0][0].odd ^= round_constants[r].odd;
+ ctx->A[0][0].evn ^= round_constants[r].evn;
+ }
+}
+
+static void extract(cf_sha3_context *ctx, uint8_t *out, size_t nbytes)
+{
+ uint16_t lanes = (nbytes + 7) / 8;
+
+ for (uint16_t x = 0, y = 0, i = 0; i < lanes; i++)
+ {
+ if (nbytes >= 8)
+ {
+ write64_bi(&ctx->A[x][y], out);
+ out += 8;
+ nbytes -= 8;
+ } else {
+ uint8_t buf[8];
+ write64_bi(&ctx->A[x][y], buf);
+ memcpy(out, buf, nbytes);
+ out += nbytes;
+ nbytes = 0;
+ }
+
+ x++;
+ if (x == 5)
+ {
+ y++;
+ x = 0;
+ }
+ }
+}
+
+static void squeeze(cf_sha3_context *ctx, uint8_t *out, size_t nbytes)
+{
+ while (nbytes)
+ {
+ size_t take = MIN(nbytes, ctx->rate);
+ extract(ctx, out, take);
+ out += take;
+ nbytes -= take;
+
+ assert(nbytes == 0);
+#if 0
+ /* Note: if we ever have |H| >= rate, we need to permute
+ * after each rate-length block.
+ *
+ * This cannot currently happen. */
+ if (nbytes)
+ permute(ctx);
+#endif
+ }
+}
+
+static void sha3_block(void *vctx, const uint8_t *data)
+{
+ cf_sha3_context *ctx = vctx;
+
+ absorb(ctx, data, ctx->rate);
+ permute(ctx);
+}
+
+static void sha3_update(cf_sha3_context *ctx, const void *data, size_t nbytes)
+{
+ cf_blockwise_accumulate(ctx->partial, &ctx->npartial, ctx->rate,
+ data, nbytes,
+ sha3_block, ctx);
+}
+
+/* Padding and domain separation constants.
+ *
+ * FIPS 202 specifies that 0b01 is appended to hash function
+ * input, and 0b1111 is appended to SHAKE input.
+ *
+ * This is done in internal (little endian) bit ordering, and
+ * we convolve it with the leftmost (first) padding bit, so:
+ *
+ * Hash: 0b110
+ * SHAKE: 0b11111
+ */
+
+#define DOMAIN_HASH_PAD 0x06
+#define DOMAIN_SHAKE_PAD 0x1f
+
+static void pad(cf_sha3_context *ctx, uint8_t domain, size_t npad)
+{
+ assert(npad >= 1);
+
+ cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, ctx->rate,
+ domain, 0x00, 0x80,
+ npad,
+ sha3_block, ctx);
+}
+
+static void pad_and_squeeze(cf_sha3_context *ctx, uint8_t *out, size_t nout)
+{
+ pad(ctx, DOMAIN_HASH_PAD, ctx->rate - ctx->npartial);
+ assert(ctx->npartial == 0);
+
+ squeeze(ctx, out, nout);
+ mem_clean(ctx, sizeof *ctx);
+}
+
+/* SHA3-224 */
+void cf_sha3_224_init(cf_sha3_context *ctx)
+{
+ sha3_init(ctx, 1152, 448);
+}
+
+void cf_sha3_224_update(cf_sha3_context *ctx, const void *data, size_t nbytes)
+{
+ sha3_update(ctx, data, nbytes);
+}
+
+void cf_sha3_224_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ])
+{
+ cf_sha3_context ours = *ctx;
+ cf_sha3_224_digest_final(&ours, hash);
+}
+
+void cf_sha3_224_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ])
+{
+ pad_and_squeeze(ctx, hash, CF_SHA3_224_HASHSZ);
+}
+
+const cf_chash cf_sha3_224 = {
+ .hashsz = CF_SHA3_224_HASHSZ,
+ .blocksz = CF_SHA3_224_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha3_224_init,
+ .update = (cf_chash_update) cf_sha3_224_update,
+ .digest = (cf_chash_digest) cf_sha3_224_digest
+};
+
+/* SHA3-256 */
+void cf_sha3_256_init(cf_sha3_context *ctx)
+{
+ sha3_init(ctx, 1088, 512);
+}
+
+void cf_sha3_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes)
+{
+ sha3_update(ctx, data, nbytes);
+}
+
+void cf_sha3_256_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ])
+{
+ cf_sha3_context ours = *ctx;
+ cf_sha3_256_digest_final(&ours, hash);
+}
+
+void cf_sha3_256_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ])
+{
+ pad_and_squeeze(ctx, hash, CF_SHA3_256_HASHSZ);
+}
+
+const cf_chash cf_sha3_256 = {
+ .hashsz = CF_SHA3_256_HASHSZ,
+ .blocksz = CF_SHA3_256_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha3_256_init,
+ .update = (cf_chash_update) cf_sha3_256_update,
+ .digest = (cf_chash_digest) cf_sha3_256_digest
+};
+
+/* SHA3-384 */
+void cf_sha3_384_init(cf_sha3_context *ctx)
+{
+ sha3_init(ctx, 832, 768);
+}
+
+void cf_sha3_384_update(cf_sha3_context *ctx, const void *data, size_t nbytes)
+{
+ sha3_update(ctx, data, nbytes);
+}
+
+void cf_sha3_384_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ])
+{
+ cf_sha3_context ours = *ctx;
+ cf_sha3_384_digest_final(&ours, hash);
+}
+
+void cf_sha3_384_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ])
+{
+ pad_and_squeeze(ctx, hash, CF_SHA3_384_HASHSZ);
+}
+
+const cf_chash cf_sha3_384 = {
+ .hashsz = CF_SHA3_384_HASHSZ,
+ .blocksz = CF_SHA3_384_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha3_384_init,
+ .update = (cf_chash_update) cf_sha3_384_update,
+ .digest = (cf_chash_digest) cf_sha3_384_digest
+};
+
+/* SHA3-512 */
+void cf_sha3_512_init(cf_sha3_context *ctx)
+{
+ sha3_init(ctx, 576, 1024);
+}
+
+void cf_sha3_512_update(cf_sha3_context *ctx, const void *data, size_t nbytes)
+{
+ sha3_update(ctx, data, nbytes);
+}
+
+void cf_sha3_512_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ])
+{
+ cf_sha3_context ours = *ctx;
+ cf_sha3_512_digest_final(&ours, hash);
+}
+
+void cf_sha3_512_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ])
+{
+ pad_and_squeeze(ctx, hash, CF_SHA3_512_HASHSZ);
+}
+
+const cf_chash cf_sha3_512 = {
+ .hashsz = CF_SHA3_512_HASHSZ,
+ .blocksz = CF_SHA3_512_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha3_512_init,
+ .update = (cf_chash_update) cf_sha3_512_update,
+ .digest = (cf_chash_digest) cf_sha3_512_digest
+};
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.h
new file mode 100644
index 00000000..44895dc3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha3.h
@@ -0,0 +1,180 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef SHA3_H
+#define SHA3_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "chash.h"
+
+/**
+ * SHA3/Keccak
+ * ===========
+ * This implementation is compatible with FIPS 202,
+ * rather than the original Keccak submission.
+ *
+ */
+
+/* .. c:macro:: CF_SHA3_224_HASHSZ
+ * The output size of SHA3-224: 28 bytes. */
+#define CF_SHA3_224_HASHSZ 28
+
+/* .. c:macro:: CF_SHA3_256_HASHSZ
+ * The output size of SHA3-256: 32 bytes. */
+#define CF_SHA3_256_HASHSZ 32
+
+/* .. c:macro:: CF_SHA3_384_HASHSZ
+ * The output size of SHA3-384: 48 bytes. */
+#define CF_SHA3_384_HASHSZ 48
+
+/* .. c:macro:: CF_SHA3_512_HASHSZ
+ * The output size of SHA3-512: 64 bytes. */
+#define CF_SHA3_512_HASHSZ 64
+
+/* .. c:macro:: CF_SHA3_224_BLOCKSZ
+ * The block size of SHA3-224. */
+#define CF_SHA3_224_BLOCKSZ 144
+
+/* .. c:macro:: CF_SHA3_256_BLOCKSZ
+ * The block size of SHA3-256. */
+#define CF_SHA3_256_BLOCKSZ 136
+
+/* .. c:macro:: CF_SHA3_384_BLOCKSZ
+ * The block size of SHA3-384. */
+#define CF_SHA3_384_BLOCKSZ 104
+
+/* .. c:macro:: CF_SHA3_512_BLOCKSZ
+ * The block size of SHA3-512. */
+#define CF_SHA3_512_BLOCKSZ 72
+
+/* We use bit-interleaved internal representation. This
+ * stores a 64 bit quantity in two 32 bit words: one word
+ * contains odd bits, the other even. This means 64-bit rotations
+ * are cheaper to compute. */
+typedef struct
+{
+ uint32_t odd, evn;
+} cf_sha3_bi;
+
+/* .. c:type:: cf_sha3_context
+ * Incremental SHA3 hashing context.
+ *
+ * .. c:member:: cf_sha3_context.A
+ * Intermediate state.
+ *
+ * .. c:member:: cf_sha3_context.partial
+ * Unprocessed input.
+ *
+ * .. c:member:: cf_sha3_context.npartial
+ * Number of bytes of unprocessed input.
+ *
+ * .. c:member:: cf_sha3_context.rate
+ * Sponge absorption rate.
+ *
+ * .. c:member:: cf_sha3_context.rate
+ * Sponge capacity.
+ */
+typedef struct
+{
+ /* State is a 5x5 block of 64-bit values, for Keccak-f[1600]. */
+ cf_sha3_bi A[5][5];
+ uint8_t partial[CF_SHA3_224_BLOCKSZ];
+ size_t npartial;
+ uint16_t rate, capacity; /* rate and capacity, in bytes. */
+} cf_sha3_context;
+
+
+/* -- _init functions -- */
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_224_init(cf_sha3_context *ctx);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_256_init(cf_sha3_context *ctx);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_384_init(cf_sha3_context *ctx);
+
+/* .. c:function:: $DECL
+ * Sets up `ctx` ready to hash a new message.
+ */
+extern void cf_sha3_512_init(cf_sha3_context *ctx);
+
+/* -- _update functions -- */
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_224_update(cf_sha3_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_256_update(cf_sha3_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_384_update(cf_sha3_context *ctx, const void *data, size_t nbytes);
+
+/* .. c:function:: $DECL
+ * Hashes `nbytes` at `data`. Copies the data for processing later if there
+ * isn't enough to make a full block.
+ */
+extern void cf_sha3_512_update(cf_sha3_context *ctx, const void *data, size_t nbytes);
+
+/* -- _digest functions -- */
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_224_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_256_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_384_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hashing operation, writing result to `hash`.
+ *
+ * This leaves `ctx` unchanged.
+ */
+extern void cf_sha3_512_digest(const cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]);
+
+/* -- _digest_final functions -- */
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_224_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_224_HASHSZ]);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_256_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_256_HASHSZ]);
+
+/* .. c:function:: $DECL */
+extern void cf_sha3_384_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_384_HASHSZ]);
+
+/* .. c:function:: $DECL
+ * Finishes the hashing operation, writing result to `hash`.
+ *
+ * This destroys the contents of `ctx`.
+ */
+extern void cf_sha3_512_digest_final(cf_sha3_context *ctx, uint8_t hash[CF_SHA3_512_HASHSZ]);
+
+/* .. c:var:: cf_sha3_224
+ * .. c:var:: cf_sha3_256
+ * .. c:var:: cf_sha3_384
+ * .. c:var:: cf_sha3_512
+ * Abstract interface to SHA3 functions. See :c:type:`cf_chash` for more information.
+ */
+extern const cf_chash cf_sha3_224;
+extern const cf_chash cf_sha3_256;
+extern const cf_chash cf_sha3_384;
+extern const cf_chash cf_sha3_512;
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha512.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha512.c
new file mode 100644
index 00000000..2d1c8964
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/sha512.c
@@ -0,0 +1,248 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <string.h>
+
+#include "sha2.h"
+#include "blockwise.h"
+#include "bitops.h"
+#include "handy.h"
+#include "tassert.h"
+
+static const uint64_t K[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)
+};
+
+# define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
+# define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+# define BSIG0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
+# define BSIG1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
+# define SSIG0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7))
+# define SSIG1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
+
+void cf_sha512_init(cf_sha512_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->H[0] = UINT64_C(0x6a09e667f3bcc908);
+ ctx->H[1] = UINT64_C(0xbb67ae8584caa73b);
+ ctx->H[2] = UINT64_C(0x3c6ef372fe94f82b);
+ ctx->H[3] = UINT64_C(0xa54ff53a5f1d36f1);
+ ctx->H[4] = UINT64_C(0x510e527fade682d1);
+ ctx->H[5] = UINT64_C(0x9b05688c2b3e6c1f);
+ ctx->H[6] = UINT64_C(0x1f83d9abfb41bd6b);
+ ctx->H[7] = UINT64_C(0x5be0cd19137e2179);
+}
+
+void cf_sha384_init(cf_sha512_context *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ ctx->H[0] = UINT64_C(0xcbbb9d5dc1059ed8);
+ ctx->H[1] = UINT64_C(0x629a292a367cd507);
+ ctx->H[2] = UINT64_C(0x9159015a3070dd17);
+ ctx->H[3] = UINT64_C(0x152fecd8f70e5939);
+ ctx->H[4] = UINT64_C(0x67332667ffc00b31);
+ ctx->H[5] = UINT64_C(0x8eb44a8768581511);
+ ctx->H[6] = UINT64_C(0xdb0c2e0d64f98fa7);
+ ctx->H[7] = UINT64_C(0x47b5481dbefa4fa4);
+}
+
+static void sha512_update_block(void *vctx, const uint8_t *inp)
+{
+ cf_sha512_context *ctx = vctx;
+
+ uint64_t W[16];
+
+ uint64_t a = ctx->H[0],
+ b = ctx->H[1],
+ c = ctx->H[2],
+ d = ctx->H[3],
+ e = ctx->H[4],
+ f = ctx->H[5],
+ g = ctx->H[6],
+ h = ctx->H[7],
+ Wt;
+
+ for (size_t t = 0; t < 80; t++)
+ {
+ if (t < 16)
+ {
+ W[t] = Wt = read64_be(inp);
+ inp += 8;
+ } else {
+ Wt = SSIG1(W[(t - 2) % 16]) +
+ W[(t - 7) % 16] +
+ SSIG0(W[(t - 15) % 16]) +
+ W[(t - 16) % 16];
+ W[t % 16] = Wt;
+ }
+
+ uint64_t T1 = h + BSIG1(e) + CH(e, f, g) + K[t] + Wt;
+ uint64_t T2 = BSIG0(a) + MAJ(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+ }
+
+ ctx->H[0] += a;
+ ctx->H[1] += b;
+ ctx->H[2] += c;
+ ctx->H[3] += d;
+ ctx->H[4] += e;
+ ctx->H[5] += f;
+ ctx->H[6] += g;
+ ctx->H[7] += h;
+
+ ctx->blocks++;
+}
+
+void cf_sha512_update(cf_sha512_context *ctx, const void *data, size_t nbytes)
+{
+ cf_blockwise_accumulate(ctx->partial, &ctx->npartial, sizeof ctx->partial,
+ data, nbytes,
+ sha512_update_block, ctx);
+}
+
+void cf_sha384_update(cf_sha512_context *ctx, const void *data, size_t nbytes)
+{
+ cf_sha512_update(ctx, data, nbytes);
+}
+
+void cf_sha512_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ])
+{
+ /* We copy the context, so the finalisation doesn't effect the caller's
+ * context. This means the caller can do:
+ *
+ * x = init()
+ * x.update('hello')
+ * h1 = x.digest()
+ * x.update(' world')
+ * h2 = x.digest()
+ *
+ * to get h1 = H('hello') and h2 = H('hello world')
+ *
+ * This wouldn't work if we applied MD-padding to *ctx.
+ */
+
+ cf_sha512_context ours = *ctx;
+ cf_sha512_digest_final(&ours, hash);
+}
+
+void cf_sha512_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA512_HASHSZ])
+{
+ uint64_t digested_bytes = ctx->blocks;
+ digested_bytes = digested_bytes * CF_SHA512_BLOCKSZ + ctx->npartial;
+ uint64_t digested_bits = digested_bytes * 8;
+
+ size_t padbytes = CF_SHA512_BLOCKSZ - ((digested_bytes + 16) % CF_SHA512_BLOCKSZ);
+
+ /* Hash 0x80 00 ... block first. */
+ cf_blockwise_acc_pad(ctx->partial, &ctx->npartial, sizeof ctx->partial,
+ 0x80, 0x00, 0x00, padbytes,
+ sha512_update_block, ctx);
+
+ /* Now hash length (this is 128 bits long). */
+ uint8_t buf[8];
+ write64_be(0, buf);
+ cf_sha512_update(ctx, buf, 8);
+ write64_be(digested_bits, buf);
+ cf_sha512_update(ctx, buf, 8);
+
+ /* We ought to have got our padding calculation right! */
+ assert(ctx->npartial == 0);
+
+ write64_be(ctx->H[0], hash + 0);
+ write64_be(ctx->H[1], hash + 8);
+ write64_be(ctx->H[2], hash + 16);
+ write64_be(ctx->H[3], hash + 24);
+ write64_be(ctx->H[4], hash + 32);
+ write64_be(ctx->H[5], hash + 40);
+ write64_be(ctx->H[6], hash + 48);
+ write64_be(ctx->H[7], hash + 56);
+ memset(ctx, 0, sizeof *ctx);
+}
+
+void cf_sha384_digest(const cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ])
+{
+ uint8_t full[CF_SHA512_HASHSZ];
+ cf_sha512_digest(ctx, full);
+ memcpy(hash, full, CF_SHA384_HASHSZ);
+}
+
+void cf_sha384_digest_final(cf_sha512_context *ctx, uint8_t hash[CF_SHA384_HASHSZ])
+{
+ uint8_t full[CF_SHA512_HASHSZ];
+ cf_sha512_digest_final(ctx, full);
+ memcpy(hash, full, CF_SHA384_HASHSZ);
+}
+
+const cf_chash cf_sha384 = {
+ .hashsz = CF_SHA384_HASHSZ,
+ .blocksz = CF_SHA384_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha384_init,
+ .update = (cf_chash_update) cf_sha384_update,
+ .digest = (cf_chash_digest) cf_sha384_digest
+};
+
+const cf_chash cf_sha512 = {
+ .hashsz = CF_SHA512_HASHSZ,
+ .blocksz = CF_SHA512_BLOCKSZ,
+ .init = (cf_chash_init) cf_sha512_init,
+ .update = (cf_chash_update) cf_sha512_update,
+ .digest = (cf_chash_digest) cf_sha512_digest
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/tassert.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/tassert.h
new file mode 100644
index 00000000..58ebb4c8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/tassert.h
@@ -0,0 +1,32 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef TASSERT_H
+#define TASSERT_H
+
+/* Tiny assert
+ * -----------
+ *
+ * This is an assert(3) definition which doesn't include any
+ * strings, but just branches to abort(3) on failure.
+ */
+
+#ifndef FULL_FAT_ASSERT
+# include <stdlib.h>
+# define assert(expr) do { if (!(expr)) abort(); } while (0)
+#else
+# include <assert.h>
+#endif
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testaes.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testaes.c
new file mode 100644
index 00000000..12543bbf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testaes.c
@@ -0,0 +1,258 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "aes.h"
+#include "modes.h"
+#include "bitops.h"
+#include "gf128.h"
+
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+static void test_memclean(void)
+{
+ uint8_t buf[32], buf2[32];
+ memset(buf, 0xff, sizeof buf);
+ mem_clean(buf + 1, sizeof buf - 2);
+ TEST_CHECK(buf[0] == 0xff);
+ TEST_CHECK(buf[1] == 0x00);
+ TEST_CHECK(buf[16] == 0x00);
+ TEST_CHECK(buf[30] == 0x00);
+ TEST_CHECK(buf[31] == 0xff);
+
+ memcpy(buf2, buf, sizeof buf);
+ TEST_CHECK(buf2[0] == 0xff);
+ TEST_CHECK(buf2[1] == 0x00);
+ TEST_CHECK(buf2[16] == 0x00);
+ TEST_CHECK(buf2[30] == 0x00);
+ TEST_CHECK(buf2[31] == 0xff);
+
+ memset(buf2, 0xee, sizeof buf);
+ TEST_CHECK(buf2[0] == 0xee);
+ TEST_CHECK(buf2[1] == 0xee);
+ TEST_CHECK(buf2[2] == 0xee);
+ TEST_CHECK(buf2[3] == 0xee);
+ TEST_CHECK(buf2[30] == 0xee);
+ TEST_CHECK(buf2[31] == 0xee);
+}
+
+static void test_bitops_select(void)
+{
+ uint8_t tab8[8];
+ uint32_t tab32[32];
+
+ for (size_t i = 0; i < 8; i++)
+ tab8[i] = 1 << i;
+ for (size_t i = 0; i < 32; i++)
+ tab32[i] = 1 << i;
+
+ for (size_t i = 0; i < 8; i++)
+ {
+ TEST_CHECK(select_u8(i, tab8, 8) == tab8[i]);
+ }
+
+ for (size_t i = 0; i < 32; i++)
+ {
+ TEST_CHECK(select_u32(i, tab32, 32) == tab32[i]);
+ }
+}
+
+static void test_bitops_incr(void)
+{
+ uint8_t buf[4];
+
+#define CHECK_BE(start, add, end) \
+ { \
+ write32_be((start), buf); \
+ for (size_t i = 0; i < (add); i++) \
+ incr_be(buf, sizeof buf); \
+ TEST_CHECK(read32_be(buf) == (end)); \
+ }
+
+#define CHECK_LE(start, add, end) \
+ { \
+ write32_le((start), buf); \
+ for (size_t i = 0; i < (add); i++) \
+ incr_le(buf, sizeof buf); \
+ TEST_CHECK(read32_le(buf) == (end)); \
+ }
+
+ CHECK_BE(0, 1, 1);
+ CHECK_BE(0, 256, 256);
+ CHECK_BE(256, 256, 512);
+ CHECK_BE(0xffffffff, 1, 0);
+
+ CHECK_LE(0, 1, 1);
+ CHECK_LE(0, 256, 256);
+ CHECK_LE(0x7fffffff, 1, 0x80000000);
+ CHECK_LE(0xffffffff, 1, 0);
+
+#undef CHECK_BE
+#undef CHECK_LE
+}
+
+static void test_bitops_unaligned(void)
+{
+ uint8_t in[4], out[4];
+
+#define CHECK(outw, len, offs) \
+ { \
+ memset(out, 0, sizeof out); \
+ copy_bytes_unaligned(out, in, len, offs); \
+ TEST_CHECK(read32_be(out) == (outw)); \
+ }
+
+ write32_be(0x11223344, in);
+
+ CHECK(0x11223344, 4, 0);
+ CHECK(0x22446600, 3, 1);
+ CHECK(0x4488cd00, 3, 2);
+ CHECK(0x89119a00, 3, 3);
+ CHECK(0x12233400, 3, 4);
+ CHECK(0x24466800, 3, 5);
+ CHECK(0x488cd100, 3, 6);
+ CHECK(0x9119a200, 3, 7);
+ CHECK(0x22334400, 3, 8);
+ CHECK(0x44660000, 2, 9);
+ CHECK(0x33440000, 2, 16);
+
+#undef CHECK
+}
+
+static void test_expand(const uint8_t *key, size_t nkey,
+ const uint32_t *answer, size_t roundkeys)
+{
+ cf_aes_context ctx;
+
+ cf_aes_init(&ctx, key, nkey);
+
+ for (size_t i = 0; i < roundkeys; i++)
+ {
+ TEST_CHECK(ctx.ks[i] == answer[i]);
+ }
+}
+
+static void test_expand_128(void)
+{
+ /* This is FIPS-197 appendix A.1. */
+ const uint8_t key[] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+ };
+
+ const uint32_t answer[] = {
+ 0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c, 0xa0fafe17, 0x88542cb1,
+ 0x23a33939, 0x2a6c7605, 0xf2c295f2, 0x7a96b943, 0x5935807a, 0x7359f67f,
+ 0x3d80477d, 0x4716fe3e, 0x1e237e44, 0x6d7a883b, 0xef44a541, 0xa8525b7f,
+ 0xb671253b, 0xdb0bad00, 0xd4d1c6f8, 0x7c839d87, 0xcaf2b8bc, 0x11f915bc,
+ 0x6d88a37a, 0x110b3efd, 0xdbf98641, 0xca0093fd, 0x4e54f70e, 0x5f5fc9f3,
+ 0x84a64fb2, 0x4ea6dc4f, 0xead27321, 0xb58dbad2, 0x312bf560, 0x7f8d292f,
+ 0xac7766f3, 0x19fadc21, 0x28d12941, 0x575c006e, 0xd014f9a8, 0xc9ee2589,
+ 0xe13f0cc8, 0xb6630ca6
+ };
+
+ test_expand(key, sizeof key, answer, ARRAYCOUNT(answer));
+}
+
+static void test_expand_192(void)
+{
+ /* This is FIPS-197 appendix A.2. */
+ const uint8_t key[] = {
+ 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b,
+ 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
+ };
+
+ const uint32_t answer[] = {
+ 0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5, 0x62f8ead2, 0x522c6b7b,
+ 0xfe0c91f7, 0x2402f5a5, 0xec12068e, 0x6c827f6b, 0x0e7a95b9, 0x5c56fec2,
+ 0x4db7b4bd, 0x69b54118, 0x85a74796, 0xe92538fd, 0xe75fad44, 0xbb095386,
+ 0x485af057, 0x21efb14f, 0xa448f6d9, 0x4d6dce24, 0xaa326360, 0x113b30e6,
+ 0xa25e7ed5, 0x83b1cf9a, 0x27f93943, 0x6a94f767, 0xc0a69407, 0xd19da4e1,
+ 0xec1786eb, 0x6fa64971, 0x485f7032, 0x22cb8755, 0xe26d1352, 0x33f0b7b3,
+ 0x40beeb28, 0x2f18a259, 0x6747d26b, 0x458c553e, 0xa7e1466c, 0x9411f1df,
+ 0x821f750a, 0xad07d753, 0xca400538, 0x8fcc5006, 0x282d166a, 0xbc3ce7b5,
+ 0xe98ba06f, 0x448c773c, 0x8ecc7204, 0x01002202
+ };
+
+ test_expand(key, sizeof key, answer, ARRAYCOUNT(answer));
+}
+
+static void test_expand_256(void)
+{
+ /* And this is A.3. */
+ const uint8_t key[] = {
+ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0,
+ 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
+ 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
+ };
+
+ const uint32_t answer[] = {
+ 0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781, 0x1f352c07, 0x3b6108d7,
+ 0x2d9810a3, 0x0914dff4, 0x9ba35411, 0x8e6925af, 0xa51a8b5f, 0x2067fcde,
+ 0xa8b09c1a, 0x93d194cd, 0xbe49846e, 0xb75d5b9a, 0xd59aecb8, 0x5bf3c917,
+ 0xfee94248, 0xde8ebe96, 0xb5a9328a, 0x2678a647, 0x98312229, 0x2f6c79b3,
+ 0x812c81ad, 0xdadf48ba, 0x24360af2, 0xfab8b464, 0x98c5bfc9, 0xbebd198e,
+ 0x268c3ba7, 0x09e04214, 0x68007bac, 0xb2df3316, 0x96e939e4, 0x6c518d80,
+ 0xc814e204, 0x76a9fb8a, 0x5025c02d, 0x59c58239, 0xde136967, 0x6ccc5a71,
+ 0xfa256395, 0x9674ee15, 0x5886ca5d, 0x2e2f31d7, 0x7e0af1fa, 0x27cf73c3,
+ 0x749c47ab, 0x18501dda, 0xe2757e4f, 0x7401905a, 0xcafaaae3, 0xe4d59b34,
+ 0x9adf6ace, 0xbd10190d, 0xfe4890d1, 0xe6188d0b, 0x046df344, 0x706c631e
+ };
+
+ test_expand(key, sizeof key, answer, ARRAYCOUNT(answer));
+}
+
+static void vector(const char *input, const char *output,
+ const char *key)
+{
+ uint8_t keybuf[32], inbuf[16], outbuf[16], tmp[16];
+ size_t nkey = sizeof keybuf;
+ cf_aes_context ctx;
+
+ nkey = unhex(keybuf, 32, key);
+ unhex(inbuf, 16, input);
+ unhex(outbuf, 16, output);
+
+ cf_aes_init(&ctx, keybuf, nkey);
+ cf_aes_encrypt(&ctx, inbuf, tmp);
+ TEST_CHECK(memcmp(tmp, outbuf, 16) == 0);
+
+ cf_aes_decrypt(&ctx, outbuf, tmp);
+ TEST_CHECK(memcmp(tmp, inbuf, 16) == 0);
+ cf_aes_finish(&ctx);
+}
+
+static void test_vectors(void)
+{
+ vector("00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a",
+ "000102030405060708090a0b0c0d0e0f");
+ vector("00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191",
+ "000102030405060708090a0b0c0d0e0f1011121314151617");
+ vector("00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+}
+
+TEST_LIST = {
+ { "handy-memclean", test_memclean },
+ { "bitops-select", test_bitops_select },
+ { "bitops-incr", test_bitops_incr },
+ { "bitops-unaligned", test_bitops_unaligned },
+ { "key-expansion-128", test_expand_128 },
+ { "key-expansion-192", test_expand_192 },
+ { "key-expansion-256", test_expand_256 },
+ { "vectors", test_vectors },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c
new file mode 100644
index 00000000..f1b53e65
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testchacha20poly1305.c
@@ -0,0 +1,91 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "chacha20poly1305.h"
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+static void vector(const char *keystr,
+ const char *noncestr,
+ const char *headerstr,
+ const char *plainstr,
+ const char *cipherstr,
+ const char *tagstr)
+{
+ /* inputs */
+ uint8_t K[32], N[12], H[12], A[16];
+ uint8_t C[265], P[265];
+
+ unhex(K, sizeof K, keystr);
+ unhex(N, sizeof N, noncestr);
+ size_t headerlen = unhex(H, sizeof H, headerstr);
+ size_t plainlen = unhex(P, sizeof P, plainstr);
+ size_t cipherlen = unhex(C, sizeof C, cipherstr);
+ unhex(A, sizeof A, tagstr);
+
+ assert(cipherlen == plainlen);
+
+ /* working data */
+ uint8_t out[265], ourtag[16];
+
+ /* check encryption works. */
+ cf_chacha20poly1305_encrypt(K, N,
+ H, headerlen,
+ P, plainlen,
+ out, ourtag);
+
+ TEST_CHECK(memcmp(out, C, cipherlen) == 0);
+ TEST_CHECK(memcmp(ourtag, A, sizeof A) == 0);
+
+ /* proper decryption */
+ TEST_CHECK(0 == cf_chacha20poly1305_decrypt(K, N,
+ H, headerlen,
+ C, cipherlen,
+ A, out));
+ TEST_CHECK(0 == memcmp(out, P, plainlen));
+
+ /* failure decryption */
+ C[0] ^= 0xff;
+
+ TEST_CHECK(1 == cf_chacha20poly1305_decrypt(K, N,
+ H, headerlen,
+ C, cipherlen,
+ A, out));
+}
+
+static void test_vectors(void)
+{
+ /* Test vector from section 2.8.2. */
+ vector("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
+ "070000004041424344454647",
+ "50515253c0c1c2c3c4c5c6c7",
+ "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e",
+ "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116",
+ "1ae10b594f09e26a7e902ecbd0600691");
+
+ /* Test vector from A.5. */
+ vector("1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
+ "000000000102030405060708",
+ "f33388860000000000004e91",
+ "496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d",
+ "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b",
+ "eead9d67890cbb22392336fea1851f38");
+}
+
+TEST_LIST = {
+ { "vectors", test_vectors },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testcurve25519.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testcurve25519.c
new file mode 100644
index 00000000..a0ab8db5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testcurve25519.c
@@ -0,0 +1,56 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "curve25519.h"
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+static void test_base_mul(void)
+{
+ uint8_t secret[32];
+ uint8_t public[32];
+ uint8_t expect[32];
+
+ unhex(secret, 32, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a");
+ unhex(expect, 32, "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a");
+ cf_curve25519_mul_base(public, secret);
+ TEST_CHECK(memcmp(expect, public, 32) == 0);
+
+ unhex(secret, 32, "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb");
+ unhex(expect, 32, "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f");
+ cf_curve25519_mul_base(public, secret);
+ TEST_CHECK(memcmp(expect, public, 32) == 0);
+}
+
+static void test_mul(void)
+{
+ uint8_t scalar[32];
+ uint8_t public[32];
+ uint8_t shared[32];
+ uint8_t expect[32];
+
+ unhex(scalar, 32, "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a");
+ unhex(public, 32, "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f");
+ unhex(expect, 32, "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
+ cf_curve25519_mul(shared, scalar, public);
+ TEST_CHECK(memcmp(expect, shared, 32) == 0);
+}
+
+TEST_LIST = {
+ { "base-mul", test_base_mul },
+ { "mul", test_mul },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testdrbg.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testdrbg.c
new file mode 100644
index 00000000..253c8c0a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testdrbg.c
@@ -0,0 +1,206 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "drbg.h"
+#include "sha1.h"
+#include "sha2.h"
+
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+static void test_hashdrbg_sha256_vector(void)
+{
+ uint8_t entropy[32], nonce[16], persn[32], reseed[32], got[128], expect[128];
+
+ /* This is the first KAT from NIST's CAVP example
+ * file for SHA-256 with all inputs used; line 4360. */
+ unhex(entropy, sizeof entropy, "b87bb4de5c148d964fc0cb612d69295671780b4270fe32bf389b6f49488efe13");
+ unhex(nonce, sizeof nonce, "27eb37a0c695c4ee3c9b70b7f6b33492");
+ unhex(persn, sizeof persn, "52321406ac8a9c266b1f8d811bb871269e5824b59a0234f01d358193523bbb7c");
+ unhex(reseed, sizeof reseed, "7638267f534c4e6ee22cc6ca6ed824fd5d3d387c00b89dd791eb5ac9766385b8");
+
+ unhex(expect, sizeof expect, "de01c061651bab3cef2fc4ea89a56b6e86e74b2e9fd11ed671c97c813778a06a2c1f41b41e754a5257750c6bde9601da9d67d8d9564f4a8538b92516a2dacc496dee257b85393f2a01ad59aa3257f1b6da9566e3706d2d6d4a26e511b0c64d7dc223acb24827178afa43ca8d5a66f983d6929dc61564c4c14fc32d85765a23f7");
+
+ cf_hash_drbg_sha256 ctx;
+ cf_hash_drbg_sha256_init(&ctx, entropy, sizeof entropy, nonce, sizeof nonce, persn, sizeof persn);
+ cf_hash_drbg_sha256_reseed(&ctx, reseed, sizeof reseed, NULL, 0);
+ cf_hash_drbg_sha256_gen(&ctx, got, sizeof got);
+ cf_hash_drbg_sha256_gen(&ctx, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+
+ /* This is line 5064 from Hash_DRBG.rsp */
+ unhex(entropy, sizeof entropy, "63363377e41e86468deb0ab4a8ed683f6a134e47e014c700454e81e95358a569");
+ unhex(nonce, sizeof nonce, "808aa38f2a72a62359915a9f8a04ca68");
+ /* no persn */
+ unhex(reseed, sizeof reseed, "e62b8a8ee8f141b6980566e3bfe3c04903dad4ac2cdf9f2280010a6739bc83d3");
+ unhex(expect, sizeof expect, "04eec63bb231df2c630a1afbe724949d005a587851e1aa795e477347c8b056621c18bddcdd8d99fc5fc2b92053d8cfacfb0bb8831205fad1ddd6c071318a6018f03b73f5ede4d4d071f9de03fd7aea105d9299b8af99aa075bdb4db9aa28c18d174b56ee2a014d098896ff2282c955a81969e069fa8ce007a180183a07dfae17");
+
+ cf_hash_drbg_sha256_init(&ctx, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ cf_hash_drbg_sha256_reseed(&ctx, reseed, sizeof reseed, NULL, 0);
+ cf_hash_drbg_sha256_gen(&ctx, got, sizeof got);
+ cf_hash_drbg_sha256_gen(&ctx, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hashdrbg_sha256_vector_addnl(void)
+{
+ uint8_t entropy[32], nonce[16], reseed[32], got[128], expect[128], addnl[32];
+
+ /* Hash_DRBG.rsp, line 5230. No personlisation string, but with additional data. */
+ unhex(entropy, sizeof entropy, "9cfb7ad03be487a3b42be06e9ae44f283c2b1458cec801da2ae6532fcb56cc4c");
+ unhex(nonce, sizeof nonce, "a20765538e8db31295747ec922c13a69");
+ unhex(reseed, sizeof reseed, "96bc8014f90ebdf690db0e171b59cc46c75e2e9b8e1dc699c65c03ceb2f4d7dc");
+ unhex(expect, sizeof expect, "71c1154a2a7a3552413970bf698aa02f14f8ea95e861f801f463be27868b1b14b1b4babd9eba5915a6414ab1104c8979b1918f3094925aeab0d07d2037e613b63cbd4f79d9f95c84b47ed9b77230a57515c211f48f4af6f5edb2c308b33905db308cf88f552c8912c49b34e66c026e67b302ca65b187928a1aba9a49edbfe190");
+
+ cf_hash_drbg_sha256 ctx;
+ cf_hash_drbg_sha256_init(&ctx, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ unhex(addnl, sizeof addnl, "6fea0894052dab3c44d503950c7c72bd7b87de87cb81d3bb51c32a62f742286d");
+ cf_hash_drbg_sha256_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl);
+ unhex(addnl, sizeof addnl, "d3467c78563b74c13db7af36c2a964820f2a9b1b167474906508fdac9b2049a6");
+ cf_hash_drbg_sha256_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ unhex(addnl, sizeof addnl, "5840a11cc9ebf77b963854726a826370ffdb2fc2b3d8479e1df5dcfa3dddd10b");
+ cf_hash_drbg_sha256_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hmacdrbg_sha1_vector(void)
+{
+ uint8_t entropy[16], nonce[8], reseed[16], got[80], expect[80];
+
+ /* HMAC_DRBG.rsp, line 8. */
+ unhex(entropy, sizeof entropy, "79349bbf7cdda5799557866621c91383");
+ unhex(nonce, sizeof nonce, "1146733abf8c35c8");
+ unhex(reseed, sizeof reseed, "c7215b5b96c48e9b338c74e3e99dfedf");
+ unhex(expect, sizeof expect, "c6a16ab8d420706f0f34ab7fec5adca9d8ca3a133e159ca6ac43c6f8a2be22834a4c0a0affb10d7194f1c1a5cf7322ec1ae0964ed4bf122746e087fdb5b3e91b3493d5bb98faed49e85f130fc8a459b7");
+
+ cf_hmac_drbg ctx;
+ cf_hmac_drbg_init(&ctx, &cf_sha1, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, NULL, 0);
+ cf_hmac_drbg_gen(&ctx, got, sizeof got);
+ cf_hmac_drbg_gen(&ctx, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hmacdrbg_sha1_vector_addnl(void)
+{
+ uint8_t entropy[16], nonce[8], reseed[16], got[80], expect[80], addnl[16];
+
+ /* HMAC_DRBG.rsp, line 174. */
+ unhex(entropy, sizeof entropy, "7d7052a776fd2fb3d7191f733304ee8b");
+ unhex(nonce, sizeof nonce, "be4a0ceedca80207");
+ unhex(reseed, sizeof reseed, "49047e879d610955eed916e4060e00c9");
+ unhex(expect, sizeof expect, "a736343844fc92511391db0addd9064dbee24c8976aa259a9e3b6368aa6de4c9bf3a0effcda9cb0e9dc33652ab58ecb7650ed80467f76a849fb1cfc1ed0a09f7155086064db324b1e124f3fc9e614fcb");
+
+ cf_hmac_drbg ctx;
+ cf_hmac_drbg_init(&ctx, &cf_sha1, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ unhex(addnl, sizeof addnl, "fd8bb33aab2f6cdfbc541811861d518d");
+ cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl);
+ unhex(addnl, sizeof addnl, "99afe347540461ddf6abeb491e0715b4");
+ cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ unhex(addnl, sizeof addnl, "02f773482dd7ae66f76e381598a64ef0");
+ cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hmacdrbg_sha256_vector(void)
+{
+ uint8_t entropy[32], nonce[16], reseed[32], got[128], expect[128];
+
+ /* HMAC_DRBG.rsp, line 5064. */
+ unhex(entropy, sizeof entropy, "06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d");
+ unhex(nonce, sizeof nonce, "0e66f71edc43e42a45ad3c6fc6cdc4df");
+ unhex(reseed, sizeof reseed, "01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552");
+ unhex(expect, sizeof expect, "76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9ec3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6a38cc5b6499dc43f7f2bd09e1e0f8f5885935124");
+
+ cf_hmac_drbg ctx;
+ cf_hmac_drbg_init(&ctx, &cf_sha256, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, NULL, 0);
+ cf_hmac_drbg_gen(&ctx, got, sizeof got);
+ cf_hmac_drbg_gen(&ctx, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hmacdrbg_sha256_vector_addnl(void)
+{
+ uint8_t entropy[32], nonce[16], reseed[32], got[128], expect[128], addnl[32];
+
+ /* HMAC_DRBG.rsp, line 5230. */
+ unhex(entropy, sizeof entropy, "05ac9fc4c62a02e3f90840da5616218c6de5743d66b8e0fbf833759c5928b53d");
+ unhex(nonce, sizeof nonce, "2b89a17904922ed8f017a63044848545");
+ unhex(reseed, sizeof reseed, "2791126b8b52ee1fd9392a0a13e0083bed4186dc649b739607ac70ec8dcecf9b");
+ unhex(expect, sizeof expect, "02ddff5173da2fcffa10215b030d660d61179e61ecc22609b1151a75f1cbcbb4363c3a89299b4b63aca5e581e73c860491010aa35de3337cc6c09ebec8c91a6287586f3a74d9694b462d2720ea2e11bbd02af33adefb4a16e6b370fa0effd57d607547bdcfbb7831f54de7073ad2a7da987a0016a82fa958779a168674b56524");
+
+ cf_hmac_drbg ctx;
+ cf_hmac_drbg_init(&ctx, &cf_sha256, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ unhex(addnl, sizeof addnl, "43bac13bae715092cf7eb280a2e10a962faf7233c41412f69bc74a35a584e54c");
+ cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl);
+ unhex(addnl, sizeof addnl, "3f2fed4b68d506ecefa21f3f5bb907beb0f17dbc30f6ffbba5e5861408c53a1e");
+ cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ unhex(addnl, sizeof addnl, "529030df50f410985fde068df82b935ec23d839cb4b269414c0ede6cffea5b68");
+ cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hmacdrbg_sha512_vector(void)
+{
+ uint8_t entropy[32], nonce[16], reseed[32], got[256], expect[256];
+
+ /* HMAC_DRBG.rsp, line 10120. */
+ unhex(entropy, sizeof entropy, "48c121b18733af15c27e1dd9ba66a9a81a5579cdba0f5b657ec53c2b9e90bbf6");
+ unhex(nonce, sizeof nonce, "bbb7c777428068fad9970891f879b1af");
+ unhex(reseed, sizeof reseed, "e0ffefdadb9ccf990504d568bdb4d862cbe17ccce6e22dfcab8b4804fd21421a");
+ unhex(expect, sizeof expect, "05da6aac7d980da038f65f392841476d37fe70fbd3e369d1f80196e66e54b8fadb1d60e1a0f3d4dc173769d75fc3410549d7a843270a54a068b4fe767d7d9a59604510a875ad1e9731c8afd0fd50b825e2c50d062576175106a9981be37e02ec7c5cd0a69aa0ca65bddaee1b0de532e10cfa1f5bf6a026e47379736a099d6750ab121dbe3622b841baf8bdcbe875c85ba4b586b8b5b57b0fecbec08c12ff2a9453c47c6e32a52103d972c62ab9affb8e728a31fcefbbccc556c0f0a35f4b10ace2d96b906e36cbb72233201e536d3e13b045187b417d2449cad1edd192e061f12d22147b0a176ea8d9c4c35404395b6502ef333a813b6586037479e0fa3c6a23");
+
+ cf_hmac_drbg ctx;
+ cf_hmac_drbg_init(&ctx, &cf_sha512, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, NULL, 0);
+ cf_hmac_drbg_gen(&ctx, got, sizeof got);
+ cf_hmac_drbg_gen(&ctx, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+static void test_hmacdrbg_sha512_vector_addnl(void)
+{
+ uint8_t entropy[32], nonce[16], reseed[32], got[256], expect[256], addnl[32];
+
+ /* HMAC_DRBG.rsp, line 10286. */
+ unhex(entropy, sizeof entropy, "4686a959e17dfb96c294b09c0f7a60efb386416cfb4c8972bcc55e44a151607a");
+ unhex(nonce, sizeof nonce, "5226543b4c89321bbfb0f11f18ee3462");
+ unhex(reseed, sizeof reseed, "5ef50daaf29929047870235c17762f5df5d9ab1af656e0e215fcc6fd9fc0d85d");
+ unhex(expect, sizeof expect, "b60d8803531b2b8583d17bdf3ac7c01f3c65cf9b069862b2d39b9024b34c172b712db0704acb078a1ab1aec0390dbaee2dec9be7b234e63da481fd469a92c77bc7bb2cfca586855520e0f9e9d47dcb9bdf2a2fdfa9f2b4342ef0ea582616b55477717cfd516d46d6383257743656f7cf8b38402ba795a8c9d35a4aa88bec623313dad6ead689d152b54074f183b2fee556f554db343626cea853718f18d386bc8bebb0c07b3c5e96ceb391ffceece88864dbd3be83a613562c5c417a24807d5f9332974f045e79a9ade36994af6cf9bbeeb71d0025fcb4ad50f121cbc2df7cd12ff5a50cddfd9a4bbc6d942d743c8b8fbebe00eeccea3d14e07ff8454fa715da");
+
+ cf_hmac_drbg ctx;
+ cf_hmac_drbg_init(&ctx, &cf_sha512, entropy, sizeof entropy, nonce, sizeof nonce, NULL, 0);
+ unhex(addnl, sizeof addnl, "d2383c3e528492269e6c3b3aaa2b54fbf48731f5aa52150ce7fc644679a5e7c6");
+ cf_hmac_drbg_reseed(&ctx, reseed, sizeof reseed, addnl, sizeof addnl);
+ unhex(addnl, sizeof addnl, "c841e7a2d9d13bdb8644cd7f5d91d241a369e12dc6c9c2be50d1ed29484bff98");
+ cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ unhex(addnl, sizeof addnl, "9054cf9216af66a788d3bf6757b8987e42d4e49b325e728dc645d5e107048245");
+ cf_hmac_drbg_gen_additional(&ctx, addnl, sizeof addnl, got, sizeof got);
+ TEST_CHECK(memcmp(got, expect, sizeof got) == 0);
+}
+
+TEST_LIST = {
+ { "hashdrbg-sha256", test_hashdrbg_sha256_vector },
+ { "hashdrbg-sha256-addnl", test_hashdrbg_sha256_vector_addnl },
+ { "hmacdrbg-sha1", test_hmacdrbg_sha1_vector },
+ { "hmacdrbg-sha1-addnl", test_hmacdrbg_sha1_vector_addnl },
+ { "hmacdrbg-sha256", test_hmacdrbg_sha256_vector },
+ { "hmacdrbg-sha256-addnl", test_hmacdrbg_sha256_vector_addnl },
+ { "hmacdrbg-sha512", test_hmacdrbg_sha512_vector },
+ { "hmacdrbg-sha512-addnl", test_hmacdrbg_sha512_vector_addnl },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testmodes.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testmodes.c
new file mode 100644
index 00000000..ed96dde8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testmodes.c
@@ -0,0 +1,890 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "aes.h"
+#include "modes.h"
+#include "bitops.h"
+#include "gf128.h"
+
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+/* Some tests are too big for microcontrollers. */
+#if defined(CORTEX_M0) || defined(CORTEX_M3) || defined(CORTEX_M4)
+# define MCU_TARGET 1
+#else
+# define MCU_TARGET 0
+#endif
+
+static void test_cbc(void)
+{
+ uint8_t out[16];
+
+ const void *iv = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
+ const void *key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c";
+ const void *inp = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a";
+ const void *expect = "\x76\x49\xab\xac\x81\x19\xb2\x46\xce\xe9\x8e\x9b\x12\xe9\x19\x7d";
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, key, 16);
+
+ cf_cbc cbc;
+ cf_cbc_init(&cbc, &cf_aes, &aes, iv);
+ cf_cbc_encrypt(&cbc, inp, out, 1);
+ TEST_CHECK(memcmp(out, expect, 16) == 0);
+
+ uint8_t decrypt[16];
+ cf_cbc_init(&cbc, &cf_aes, &aes, iv);
+ cf_cbc_decrypt(&cbc, out, decrypt, 1);
+ TEST_CHECK(memcmp(decrypt, inp, 16) == 0);
+}
+
+static void cbcmac_vector(const void *tag_expect, size_t ntag,
+ const void *key, size_t nkey,
+ const void *msg, size_t nmsg)
+{
+ uint8_t tag[16];
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, key, nkey);
+
+ cf_cbcmac_stream cm;
+ cf_cbcmac_stream_init(&cm, &cf_aes, &aes);
+ cf_cbcmac_stream_update(&cm, msg, nmsg);
+ cf_cbcmac_stream_pad_final(&cm, tag);
+
+ TEST_CHECK(sizeof tag == ntag);
+ TEST_CHECK(memcmp(tag, tag_expect, sizeof tag) == 0);
+}
+
+static void test_cbcmac(void)
+{
+ cbcmac_vector("\xf0\xf1\x89\x75\xa0\x85\x9d\x13\xa4\x9d\x3d\xbf\xc6\xcd\x65\xd9", 16, "\x04\xf7\xf7\x78\x62\x1d\x1e\x2c\x86\x47\x82\x2a\x50\xd9\x8a\x83", 16, "\x83\x1b\xe7\x4b\x9b\xe6\x85\xc8\x38\xe2\x2a\x25\xa3\x11\xcb\x14\x79\x62\x35\xf5\x28\x98\xd0", 23);
+ cbcmac_vector("\x0d\x6a\x13\x8f\x75\xb7\x56\x94\xd5\x15\xc5\x55\x5e\xee\xdd\x92", 16, "\xff\x84\x5a\xfc\x51\xf2\x06\x35\xa4\x8f\x6c\xec\x9f\x78\x1f\x2e", 16, "\xc5\x85\x3e\x6b\x3f\x7e\xf5\x10\x93\x6e\x30\xd5\x54\x13\x5f\x0d\x55\x43\x92\x8c\x53\xfc\x2f\x81\xa3", 25);
+ cbcmac_vector("\x96\x81\x3d\xb1\x7e\xac\x06\xb9\x79\x42\xa7\x3a\x7c\x5a\x0a\xad", 16, "\x10\x77\x16\x47\x23\x2e\xda\x40\x23\xd7\xc5\xc9\xbb\x51\x2e\x93", 16, "\x06\x53\x5f\x70\xd9\x6c\x80\x50\x85\x6b\x02\x4f\x67\xae\x87\xde\xc8\xd2\x9d\xab\xb7\x1f\x55\x93\x51\x00\x0a\x3c\x8f\xfc\x63\x60", 32);
+ cbcmac_vector("\x20\xdd\xa5\xb1\xc1\x14\x00\x90\x97\x41\xef\x3b\xc6\xac\xe8\xec", 16, "\x5b\x39\xdb\x4b\xa4\x53\x1f\x97\xf9\xca\x4b\xdd\xed\x9b\x28\x53", 16, "\x49\x91\xb3\x35\x40\xda\x4d\x8a\xdf\xe9\x37\x4b\xb4\xe1\xc5", 15);
+ cbcmac_vector("\xc0\x2f\x8f\x0a\xba\x13\x4b\x6b\x16\x69\xfb\x58\x2f\xc1\xc8\x76", 16, "\xd0\x22\xc7\xe7\x85\xd2\xfc\xa4\xd6\x7f\xaa\x18\xb1\xa9\xfd\x9d\x7a\x47\x37\x09\x33\x43\x06\x32", 24, "\x2b\xa2\x8e\xa5\x62\xdd\x9c\x5e\x80\xcc\xaf\x80\x16\x77", 14);
+ cbcmac_vector("\x05\x79\x4b\x5f\xc8\xf2\xee\x87\x74\xcd\x88\x9f\x7c\x29\xeb\xa0", 16, "\xe4\x51\xdb\x26\x8e\x2a\x26\xd1\xbf\x78\x3e\xab\x5d\xc6\xf9\x3f\xb2\xc5\xe2\x5c\xe8\x61\x28\x3c", 24, "\xea\x14\xfa\xaa\x95\x48\x12\xcb", 8);
+ cbcmac_vector("\x6a\x14\x4b\xaa\x39\xf6\x19\x71\x62\x65\xd3\x4e\x53\xb4\xc6\x7c", 16, "\xff\x46\x38\x0f\x62\xa9\x37\x7f\xb2\x41\x88\x44\x39\x2a\x97\xf5\xb9\x9a\xc0\x37\xf9\xc6\x75\x3f", 24, "\x64\x04\x53\x4c\xa8\x0a\x60\xf6\x5e\x22\xb6\xc4\xd7\xf3\xa9\x33\xf9\x3e", 18);
+ cbcmac_vector("\xf7\x1d\x16\x5c\xba\xac\x0f\xf0\x1a\x12\x75\xf8\x5b\x6a\x8e\x15", 16, "\x67\xce\x47\x6c\x11\x0e\xa1\xbc\xf0\x81\x30\x2b\x5f\xe2\x3b\xbc\x34\xc5\x4d\x46\x01\xed\x49\x04", 24, "\x94\xb1\x25\x63\x49\x49\x46\x7e\x7a\xa0\x0e\xa1\x10\x25\x21\x9a\xc9\x1f\x0d\xed\xa1\x10\x30\x7e\x08\x84\xee\x09\xe8\x31\x53\x81", 32);
+ cbcmac_vector("\x22\xfb\x7e\x4c\x77\x12\x7c\xed\x2c\xaa\xf9\x8d\x9f\x35\x15\x60", 16, "\x1c\x50\xc0\x79\x7c\xd6\x7f\x89\x26\xd1\xc9\xb9\x85\xf9\xee\xaf\x18\x3f\x07\x0b\x3a\xd2\x5f\x7e\xfa\x08\x95\xfe\x98\xe3\x43\x91", 32, "\x7d\x1e\x7e\x19\x9a\xd4\xf4\x3f\xcf\xff\x55\xf7\xc9\x81\xe6\x13\xc0\x22\xab\x7f\x83\x92\x21\x72\x65\x79\x78\xcd\xf0\x8b\x36", 31);
+ cbcmac_vector("\x40\xc1\xef\xf3\xf4\x71\x54\x58\x77\x3c\xd3\x07\x96\xdf\xfd\x54", 16, "\x3c\x1e\xae\xa7\x4a\xf6\xee\x43\x9b\xd7\xa3\x76\x38\xd6\x08\x21\x60\xe6\x1b\x23\x2b\xf8\xa4\x5d\x05\xd5\xf4\x89\x04\x3e\x2d\x19", 32, "\xd2\xa3\x38\x1a\x82\xd6\xb6\xc2\x52\x93\x43\x1d\xdc\x1d\x73\xb5\x14\x82\x40\xfe\x00\xc3\x24\x52\x8d\x69\xc6\x11\x4e\x4c\xa9\x40\xcd\xfb\x29\x17", 36);
+ cbcmac_vector("\x69\x7c\x65\x95\xa2\x1f\xa2\xfa\x3a\xd3\x60\x68\x7a\xed\x68\x37", 16, "\xc2\xda\x01\xb4\x12\xa5\xcd\x1c\x75\xb5\x08\x5f\xd2\xee\x79\xc3\x47\xd9\xf9\x12\x86\x3d\x81\xd0\x42\x89\x75\x96\x58\x70\x47\x05", 32, "\x65\x22\x9b\x77\x15\xe5\x02\x54\x04\x90\xfb\xe2\xbf\x5a\x8e\xb0\xbf\x64\xff\x7f\xb7\xab\x7f\x18\x69\x7b", 26);
+ cbcmac_vector("\xf5\x2d\x65\x16\x84\x43\x0d\xe8\x1f\x29\x51\x06\xec\xf0\xa5\xd2", 16, "\x76\xff\xb3\x38\x5b\xca\x7c\x93\xc0\x12\xd7\xbc\xb3\xa3\xd0\xf2\x87\xa7\x0a\x91\x36\x76\xa7\x8d\x28\x47\x05\x8e\x75\xae\x5e\x3c", 32, "\x12\x90\x91\x65\x32\x37\xd0\x35\xf6\x40\x42\xa7\x4f\x61\xa9\x9c\x8f\xd6\x84\x9a\x86\x0e\x57\xe7\xe4", 25);
+}
+
+static void test_ctr(void)
+{
+ uint8_t out[16];
+
+ const void *nonce = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
+ const void *key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c";
+ const void *inp = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a";
+ const void *expect = "\x87\x4d\x61\x91\xb6\x20\xe3\x26\x1b\xef\x68\x64\x99\x0d\xb6\xce";
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, key, 16);
+
+ cf_ctr ctr;
+ cf_ctr_init(&ctr, &cf_aes, &aes, nonce);
+ cf_ctr_cipher(&ctr, inp, out, 16); /* one piece */
+ TEST_CHECK(memcmp(expect, out, 16) == 0);
+
+ cf_ctr_init(&ctr, &cf_aes, &aes, nonce);
+ cf_ctr_cipher(&ctr, inp, out, 1); /* incremental (2 blocks) */
+ cf_ctr_cipher(&ctr, inp, out, 16);
+ cf_ctr_cipher(&ctr, inp, out, 16);
+
+ cf_ctr_init(&ctr, &cf_aes, &aes, nonce);
+ cf_ctr_cipher(&ctr, inp, out, 1); /* incremental */
+ cf_ctr_cipher(&ctr, ((uint8_t *)inp) + 1, out + 1, 15);
+ TEST_CHECK(memcmp(expect, out, 16) == 0);
+
+ uint8_t decrypt[16];
+ cf_ctr_init(&ctr, &cf_aes, &aes, nonce);
+ cf_ctr_cipher(&ctr, out, decrypt, 16);
+ TEST_CHECK(memcmp(decrypt, inp, 16) == 0);
+
+ /* Test we use the right number of blocks up. */
+ uint8_t test_nonce[16], test_inp[16];
+ memset(test_nonce, 0xff, 16);
+ memset(test_inp, 0x00, 16);
+ cf_ctr_init(&ctr, &cf_aes, &aes, test_nonce);
+
+ /* Exercise cf_blockwise_xor code paths. */
+ for (int i = 0; i < 1024; i++)
+ {
+ cf_ctr_cipher(&ctr, test_inp, out, i % 16);
+ }
+
+ /* expected counter value is 1024 * 7.5 / 16 - 1:
+ * 479 = 0x1df
+ */
+
+ memset(test_nonce, 0, sizeof test_nonce);
+ test_nonce[15] = 0xdf;
+ test_nonce[14] = 0x01;
+
+ TEST_CHECK(memcmp(test_nonce, ctr.nonce, 16) == 0);
+}
+
+static void check_eax(const void *key, size_t nkey,
+ const void *msg, size_t nmsg,
+ const void *nonce, size_t nnonce,
+ const void *header, size_t nheader,
+ const void *expect_cipher,
+ const void *expect_tag, size_t ntag)
+{
+ uint8_t cipher[32];
+ uint8_t tag[16];
+
+ assert(nmsg <= sizeof cipher);
+ assert(ntag <= ntag);
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, key, nkey);
+
+ cf_eax_encrypt(&cf_aes, &aes,
+ msg, nmsg,
+ header, nheader,
+ nonce, nnonce,
+ cipher,
+ tag, ntag);
+
+ TEST_CHECK(memcmp(expect_cipher, cipher, nmsg) == 0);
+ TEST_CHECK(memcmp(expect_tag, tag, ntag) == 0);
+
+ int rc;
+ uint8_t tmp[sizeof cipher];
+ rc = cf_eax_decrypt(&cf_aes, &aes,
+ cipher, nmsg,
+ header, nheader,
+ nonce, nnonce,
+ tag, ntag,
+ tmp);
+ TEST_CHECK(rc == 0);
+ TEST_CHECK(memcmp(tmp, msg, nmsg) == 0);
+
+ tag[0] ^= 0xff;
+ rc = cf_eax_decrypt(&cf_aes, &aes,
+ cipher, nmsg,
+ header, nheader,
+ nonce, nnonce,
+ tag, ntag,
+ tmp);
+ TEST_CHECK(rc == 1);
+}
+
+static void test_eax(void)
+{
+ /* Test vectors from paper. */
+ check_eax("\x23\x39\x52\xDE\xE4\xD5\xED\x5F\x9B\x9C\x6D\x6F\xF8\x0F\xF4\x78", 16,
+ "", 0,
+ "\x62\xEC\x67\xF9\xC3\xA4\xA4\x07\xFC\xB2\xA8\xC4\x90\x31\xA8\xB3", 16,
+ "\x6B\xFB\x91\x4F\xD0\x7E\xAE\x6B", 8,
+ "",
+ "\xE0\x37\x83\x0E\x83\x89\xF2\x7B\x02\x5A\x2D\x65\x27\xE7\x9D\x01", 16);
+
+ check_eax("\x91\x94\x5D\x3F\x4D\xCB\xEE\x0B\xF4\x5E\xF5\x22\x55\xF0\x95\xA4", 16,
+ "\xF7\xFB", 2,
+ "\xBE\xCA\xF0\x43\xB0\xA2\x3D\x84\x31\x94\xBA\x97\x2C\x66\xDE\xBD", 16,
+ "\xFA\x3B\xFD\x48\x06\xEB\x53\xFA", 8,
+ "\x19\xDD",
+ "\x5C\x4C\x93\x31\x04\x9D\x0B\xDA\xB0\x27\x74\x08\xF6\x79\x67\xE5", 16);
+
+ check_eax("\x01\xF7\x4A\xD6\x40\x77\xF2\xE7\x04\xC0\xF6\x0A\xDA\x3D\xD5\x23", 16,
+ "\x1A\x47\xCB\x49\x33", 5,
+ "\x70\xC3\xDB\x4F\x0D\x26\x36\x84\x00\xA1\x0E\xD0\x5D\x2B\xFF\x5E", 16,
+ "\x23\x4A\x34\x63\xC1\x26\x4A\xC6", 8,
+ "\xD8\x51\xD5\xBA\xE0",
+ "\x3A\x59\xF2\x38\xA2\x3E\x39\x19\x9D\xC9\x26\x66\x26\xC4\x0F\x80", 16);
+
+ check_eax("\xD0\x7C\xF6\xCB\xB7\xF3\x13\xBD\xDE\x66\xB7\x27\xAF\xD3\xC5\xE8", 16,
+ "\x48\x1C\x9E\x39\xB1", 5,
+ "\x84\x08\xDF\xFF\x3C\x1A\x2B\x12\x92\xDC\x19\x9E\x46\xB7\xD6\x17", 16,
+ "\x33\xCC\xE2\xEA\xBF\xF5\xA7\x9D", 8,
+ "\x63\x2A\x9D\x13\x1A",
+ "\xD4\xC1\x68\xA4\x22\x5D\x8E\x1F\xF7\x55\x93\x99\x74\xA7\xBE\xDE", 16);
+
+ check_eax("\x35\xB6\xD0\x58\x00\x05\xBB\xC1\x2B\x05\x87\x12\x45\x57\xD2\xC2", 16,
+ "\x40\xD0\xC0\x7D\xA5\xE4", 6,
+ "\xFD\xB6\xB0\x66\x76\xEE\xDC\x5C\x61\xD7\x42\x76\xE1\xF8\xE8\x16", 16,
+ "\xAE\xB9\x6E\xAE\xBE\x29\x70\xE9", 8,
+ "\x07\x1D\xFE\x16\xC6\x75",
+ "\xCB\x06\x77\xE5\x36\xF7\x3A\xFE\x6A\x14\xB7\x4E\xE4\x98\x44\xDD", 16);
+
+ check_eax("\xBD\x8E\x6E\x11\x47\x5E\x60\xB2\x68\x78\x4C\x38\xC6\x2F\xEB\x22", 16,
+ "\x4D\xE3\xB3\x5C\x3F\xC0\x39\x24\x5B\xD1\xFB\x7D", 12,
+ "\x6E\xAC\x5C\x93\x07\x2D\x8E\x85\x13\xF7\x50\x93\x5E\x46\xDA\x1B", 16,
+ "\xD4\x48\x2D\x1C\xA7\x8D\xCE\x0F", 8,
+ "\x83\x5B\xB4\xF1\x5D\x74\x3E\x35\x0E\x72\x84\x14",
+ "\xAB\xB8\x64\x4F\xD6\xCC\xB8\x69\x47\xC5\xE1\x05\x90\x21\x0A\x4F", 16);
+
+ check_eax("\x7C\x77\xD6\xE8\x13\xBE\xD5\xAC\x98\xBA\xA4\x17\x47\x7A\x2E\x7D", 16,
+ "\x8B\x0A\x79\x30\x6C\x9C\xE7\xED\x99\xDA\xE4\xF8\x7F\x8D\xD6\x16\x36", 17,
+ "\x1A\x8C\x98\xDC\xD7\x3D\x38\x39\x3B\x2B\xF1\x56\x9D\xEE\xFC\x19", 16,
+ "\x65\xD2\x01\x79\x90\xD6\x25\x28", 8,
+ "\x02\x08\x3E\x39\x79\xDA\x01\x48\x12\xF5\x9F\x11\xD5\x26\x30\xDA\x30",
+ "\x13\x73\x27\xD1\x06\x49\xB0\xAA\x6E\x1C\x18\x1D\xB6\x17\xD7\xF2", 16);
+
+ check_eax("\x5F\xFF\x20\xCA\xFA\xB1\x19\xCA\x2F\xC7\x35\x49\xE2\x0F\x5B\x0D", 16,
+ "\x1B\xDA\x12\x2B\xCE\x8A\x8D\xBA\xF1\x87\x7D\x96\x2B\x85\x92\xDD\x2D\x56", 18,
+ "\xDD\xE5\x9B\x97\xD7\x22\x15\x6D\x4D\x9A\xFF\x2B\xC7\x55\x98\x26", 16,
+ "\x54\xB9\xF0\x4E\x6A\x09\x18\x9A", 8,
+ "\x2E\xC4\x7B\x2C\x49\x54\xA4\x89\xAF\xC7\xBA\x48\x97\xED\xCD\xAE\x8C\xC3",
+ "\x3B\x60\x45\x05\x99\xBD\x02\xC9\x63\x82\x90\x2A\xEF\x7F\x83\x2A", 16);
+
+ check_eax("\xA4\xA4\x78\x2B\xCF\xFD\x3E\xC5\xE7\xEF\x6D\x8C\x34\xA5\x61\x23", 16,
+ "\x6C\xF3\x67\x20\x87\x2B\x85\x13\xF6\xEA\xB1\xA8\xA4\x44\x38\xD5\xEF\x11", 18,
+ "\xB7\x81\xFC\xF2\xF7\x5F\xA5\xA8\xDE\x97\xA9\xCA\x48\xE5\x22\xEC", 16,
+ "\x89\x9A\x17\x58\x97\x56\x1D\x7E", 8,
+ "\x0D\xE1\x8F\xD0\xFD\xD9\x1E\x7A\xF1\x9F\x1D\x8E\xE8\x73\x39\x38\xB1\xE8",
+ "\xE7\xF6\xD2\x23\x16\x18\x10\x2F\xDB\x7F\xE5\x5F\xF1\x99\x17\x00", 16);
+
+ check_eax("\x83\x95\xFC\xF1\xE9\x5B\xEB\xD6\x97\xBD\x01\x0B\xC7\x66\xAA\xC3", 16,
+ "\xCA\x40\xD7\x44\x6E\x54\x5F\xFA\xED\x3B\xD1\x2A\x74\x0A\x65\x9F\xFB\xBB\x3C\xEA\xB7", 21,
+ "\x22\xE7\xAD\xD9\x3C\xFC\x63\x93\xC5\x7E\xC0\xB3\xC1\x7D\x6B\x44", 16,
+ "\x12\x67\x35\xFC\xC3\x20\xD2\x5A", 8,
+ "\xCB\x89\x20\xF8\x7A\x6C\x75\xCF\xF3\x96\x27\xB5\x6E\x3E\xD1\x97\xC5\x52\xD2\x95\xA7",
+ "\xCF\xC4\x6A\xFC\x25\x3B\x46\x52\xB1\xAF\x37\x95\xB1\x24\xAB\x6E", 16);
+
+ /* Test vector from bug #3 */
+ check_eax("\x58\x94\x17\xB0\x32\x4B\x1B\x71\xD7\xA6\x75\x18\x52\x86\x7A\xE8", 16,
+ "\x00\x00\x1C\x40\x00\x00\x00\x48\x00\x00\x00\x73", 12,
+ "\x00\x01\x00\x00\xF6\x83", 6,
+ "", 0,
+ "\xD5\xD8\x99\x79\xAE\x79\xEB\xEE\x4E\x38\x5F\xA5",
+ "\x0E\xFB\x21\xFA\xD7\x14\xA2\x5B\x44\x14\x5F\x79\x22\x1A\x2C\x9A", 16);
+
+}
+
+static void check_cmac(const void *key, size_t nkey,
+ const void *msg, size_t nmsg,
+ const void *wanttag, size_t ntag)
+{
+ uint8_t gottag[16];
+
+ TEST_CHECK(cf_aes.blocksz == ntag);
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, key, nkey);
+
+ cf_cmac cmac;
+ cf_cmac_init(&cmac, &cf_aes, &aes);
+ cf_cmac_sign(&cmac, msg, nmsg, gottag);
+
+ TEST_CHECK(memcmp(gottag, wanttag, cf_aes.blocksz) == 0);
+}
+
+static void test_cmac(void)
+{
+ /* These from SP800-38B */
+ check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "", 0,
+ "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12\x9b\x75\x67\x46", 16);
+ check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16,
+ "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c", 16);
+ check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", 40,
+ "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61\x14\x97\xc8\x27", 16);
+ check_cmac("\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64,
+ "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17\x79\x36\x3c\xfe", 16);
+
+ check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24,
+ "", 0,
+ "\xd1\x7d\xdf\x46\xad\xaa\xcd\xe5\x31\xca\xc4\x83\xde\x7a\x93\x67", 16);
+ check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16,
+ "\x9e\x99\xa7\xbf\x31\xe7\x10\x90\x06\x62\xf6\x5e\x61\x7c\x51\x84", 16);
+ check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", 40,
+ "\x8a\x1d\xe5\xbe\x2e\xb3\x1a\xad\x08\x9a\x82\xe6\xee\x90\x8b\x0e", 16);
+ check_cmac("\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64,
+ "\xa1\xd5\xdf\x0e\xed\x79\x0f\x79\x4d\x77\x58\x96\x59\xf3\x9a\x11", 16);
+
+ check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32,
+ "", 0,
+ "\x02\x89\x62\xf6\x1b\x7b\xf8\x9e\xfc\x6b\x55\x1f\x46\x67\xd9\x83", 16);
+ check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16,
+ "\x28\xa7\x02\x3f\x45\x2e\x8f\x82\xbd\x4b\xf2\x8d\x8c\x37\xc3\x5c", 16);
+ check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", 40,
+ "\xaa\xf3\xd8\xf1\xde\x56\x40\xc2\x32\xf5\xb1\x69\xb9\xc9\x11\xe6", 16);
+ check_cmac("\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64,
+ "\xe1\x99\x21\x90\x54\x9f\x6e\xd5\x69\x6a\x2c\x05\x6c\x31\x54\x10", 16);
+}
+
+static void test_gf128_mul(void)
+{
+ uint8_t bout[16];
+
+ const void *bx = "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78";
+ const void *by = "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e";
+ const void *bexpect = "\x5e\x2e\xc7\x46\x91\x70\x62\x88\x2c\x85\xb0\x68\x53\x53\xde\xb7";
+
+ cf_gf128 x, y, out;
+ cf_gf128_frombytes_be(bx, x);
+ cf_gf128_frombytes_be(by, y);
+ cf_gf128_mul(x, y, out);
+ cf_gf128_tobytes_be(out, bout);
+ TEST_CHECK(memcmp(bexpect, bout, 16) == 0);
+}
+
+static void check_gcm(const void *key, size_t nkey,
+ const void *plain, size_t nplain,
+ const void *aad, size_t naad,
+ const void *iv, size_t niv,
+ const void *cipher_expect, size_t ncipher,
+ const void *tag_expect, size_t ntag)
+{
+ uint8_t plain_decrypt[64],
+ cipher[64],
+ tag[16];
+
+ assert(ncipher == nplain);
+
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, nkey);
+
+ cf_gcm_encrypt(&cf_aes, &ctx,
+ plain, nplain,
+ aad, naad,
+ iv, niv,
+ cipher,
+ tag, ntag);
+
+ TEST_CHECK(memcmp(tag, tag_expect, ntag) == 0);
+ TEST_CHECK(memcmp(cipher, cipher_expect, ncipher) == 0);
+
+ int err = cf_gcm_decrypt(&cf_aes, &ctx,
+ cipher, ncipher,
+ aad, naad,
+ iv, niv,
+ tag, ntag,
+ plain_decrypt);
+ TEST_CHECK(err == 0);
+ TEST_CHECK(memcmp(plain_decrypt, plain, ncipher) == 0);
+
+ tag[0] ^= 0xff;
+ err = cf_gcm_decrypt(&cf_aes, &ctx,
+ cipher, ncipher,
+ aad, naad,
+ iv, niv,
+ tag, ntag,
+ plain_decrypt);
+ TEST_CHECK(err == 1);
+}
+
+static void test_gcm(void)
+{
+ check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16,
+ "", 0,
+ "", 0,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45\x5a", 16);
+ check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16,
+ "", 0,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", 16,
+ "\xab\x6e\x47\xd4\x2c\xec\x13\xbd\xf5\x3a\x67\xb2\x12\x57\xbd\xdf", 16);
+ check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16,
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+ "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+ "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55", 64,
+ "", 0,
+ "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12,
+ "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
+ "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
+ "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
+ "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85", 64,
+ "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4", 16);
+ check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16,
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+ "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+ "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60,
+ "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+ "\xab\xad\xda\xd2", 20,
+ "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12,
+ "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
+ "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
+ "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
+ "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91", 60,
+ "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb\x94\xfa\xe9\x5a\xe7\x12\x1a\x47", 16);
+ check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16,
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+ "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+ "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60,
+ "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+ "\xab\xad\xda\xd2", 20,
+ "\xca\xfe\xba\xbe\xfa\xce\xdb\xad", 8,
+ "\x61\x35\x3b\x4c\x28\x06\x93\x4a\x77\x7f\xf5\x1f\xa2\x2a\x47\x55"
+ "\x69\x9b\x2a\x71\x4f\xcd\xc6\xf8\x37\x66\xe5\xf9\x7b\x6c\x74\x23"
+ "\x73\x80\x69\x00\xe4\x9f\x24\xb2\x2b\x09\x75\x44\xd4\x89\x6b\x42"
+ "\x49\x89\xb5\xe1\xeb\xac\x0f\x07\xc2\x3f\x45\x98", 60,
+ "\x36\x12\xd2\xe7\x9e\x3b\x07\x85\x56\x1b\xe1\x4a\xac\xa2\xfc\xcb", 16);
+ check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16,
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+ "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+ "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60,
+ "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+ "\xab\xad\xda\xd2", 20,
+ "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa"
+ "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28"
+ "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54"
+ "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60,
+ "\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94"
+ "\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7"
+ "\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f"
+ "\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5", 60,
+ "\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50", 16);
+
+ check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", 16,
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+ "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+ "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", 60,
+ "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+ "\xab\xad\xda\xd2", 20,
+ "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa"
+ "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28"
+ "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54"
+ "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60,
+ "\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94"
+ "\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7"
+ "\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f"
+ "\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5", 60,
+ "\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50", 16);
+ check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24,
+ "", 0,
+ "", 0,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b\xa0\x0e\xd1\xf3\x12\x57\x24\x35", 16);
+ check_gcm("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16,
+ "", 0,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "\x98\xe7\x24\x7c\x07\xf0\xfe\x41\x1c\x26\x7e\x43\x84\xb0\xf6\x00", 16,
+ "\x2f\xf5\x8d\x80\x03\x39\x27\xab\x8e\xf4\xd4\x58\x75\x14\xf0\xfb", 16);
+ check_gcm("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+ "\xfe\xff\xe9\x92\x86\x65\x73\x1c", 24,
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+ "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+ "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+ "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55", 64,
+ "", 0,
+ "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12,
+ "\x39\x80\xca\x0b\x3c\x00\xe8\x41\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
+ "\x85\x9e\x1c\xea\xa6\xef\xd9\x84\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
+ "\x7d\x77\x3d\x00\xc1\x44\xc5\x25\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
+ "\x18\xe2\x44\x8b\x2f\xe3\x24\xd9\xcc\xda\x27\x10\xac\xad\xe2\x56", 64,
+ "\x99\x24\xa7\xc8\x58\x73\x36\xbf\xb1\x18\x02\x4d\xb8\x67\x4a\x14", 16);
+}
+
+static void check_ccm(const void *key, size_t nkey,
+ const void *header, size_t nheader,
+ const void *plain, size_t nplain,
+ const void *nonce, size_t nnonce,
+ const void *expect_cipher, size_t ncipher,
+ const void *expect_tag, size_t ntag)
+{
+ uint8_t cipher[32], tag[16], decrypted[32];
+
+ assert(ncipher == nplain);
+
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, nkey);
+
+ cf_ccm_encrypt(&cf_aes, &ctx,
+ plain, nplain, 15 - nnonce,
+ header, nheader,
+ nonce, nnonce,
+ cipher,
+ tag, ntag);
+
+ TEST_CHECK(memcmp(tag, expect_tag, ntag) == 0);
+ TEST_CHECK(memcmp(cipher, expect_cipher, ncipher) == 0);
+
+ int err;
+ err = cf_ccm_decrypt(&cf_aes, &ctx,
+ expect_cipher, ncipher, 15 - nnonce,
+ header, nheader,
+ nonce, nnonce,
+ tag, ntag,
+ decrypted);
+ TEST_CHECK(err == 0);
+ TEST_CHECK(memcmp(decrypted, plain, nplain) == 0);
+
+ tag[0] ^= 0xff;
+
+ err = cf_ccm_decrypt(&cf_aes, &ctx,
+ expect_cipher, ncipher, 15 - nnonce,
+ header, nheader,
+ nonce, nnonce,
+ tag, ntag,
+ decrypted);
+ TEST_CHECK(err == 1);
+}
+
+#if !MCU_TARGET
+static void fill(uint8_t *buf, size_t len, uint8_t b)
+{
+ for (size_t i = 0; i < len; i++)
+ buf[i] = b++;
+}
+
+static void test_ccm_long(void)
+{
+ /* This is example 4 from SP800-38C, to test the long AAD code path. */
+ uint8_t header[0x10000];
+ uint8_t key[16];
+ uint8_t tag[14];
+ uint8_t nonce[13];
+ uint8_t plain[32], cipher[32];
+
+ fill(header, sizeof header, 0x00);
+ fill(key, sizeof key, 0x40);
+ fill(nonce, sizeof nonce, 0x10);
+ fill(plain, sizeof plain, 0x20);
+
+ const void *expect_tag = "\xb4\xac\x6b\xec\x93\xe8\x59\x8e\x7f\x0d\xad\xbc\xea\x5b";
+ const void *expect_cipher = "\x69\x91\x5d\xad\x1e\x84\xc6\x37\x6a\x68\xc2\x96\x7e\x4d\xab\x61\x5a\xe0\xfd\x1f\xae\xc4\x4c\xc4\x84\x82\x85\x29\x46\x3c\xcf\x72";
+
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, sizeof key);
+
+ cf_ccm_encrypt(&cf_aes, &ctx,
+ plain, sizeof plain, 15 - sizeof nonce,
+ header, sizeof header,
+ nonce, sizeof nonce,
+ cipher,
+ tag, sizeof tag);
+
+ TEST_CHECK(memcmp(expect_tag, tag, sizeof tag) == 0);
+ TEST_CHECK(memcmp(expect_cipher, cipher, sizeof cipher) == 0);
+}
+#endif
+
+static void test_ccm(void)
+{
+ check_ccm("\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07", 8,
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e", 23,
+ "\x00\x00\x00\x03\x02\x01\x00\xa0\xa1\xa2\xa3\xa4\xa5", 13,
+ "\x58\x8c\x97\x9a\x61\xc6\x63\xd2\xf0\x66\xd0\xc2\xc0\xf9\x89\x80\x6d\x5f\x6b\x61\xda\xc3\x84", 23,
+ "\x17\xe8\xd1\x2c\xfd\xf9\x26\xe0", 8);
+
+ check_ccm("\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07", 8,
+ "\x20\x21\x22\x23", 4,
+ "\x10\x11\x12\x13\x14\x15\x16", 7,
+ "\x71\x62\x01\x5b", 4,
+ "\x4d\xac\x25\x5d", 4);
+
+ check_ccm("\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13", 20,
+ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37", 24,
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b", 12,
+ "\xe3\xb2\x01\xa9\xf5\xb7\x1a\x7a\x9b\x1c\xea\xec\xcd\x97\xe7\x0b\x61\x76\xaa\xd9\xa4\x42\x8a\xa5", 24,
+ "\x48\x43\x92\xfb\xc1\xb0\x99\x51", 8);
+}
+
+static void check_ocb(const void *key, size_t nkey,
+ const void *header, size_t nheader,
+ const void *plain, size_t nplain,
+ const void *nonce, size_t nnonce,
+ const void *expect_cipher, size_t ncipher,
+ const void *expect_tag, size_t ntag)
+{
+ uint8_t cipher[40], tag[16];
+
+ assert(ncipher == nplain);
+ assert(ncipher <= sizeof cipher);
+ assert(ntag <= sizeof tag);
+
+ cf_aes_context ctx;
+ cf_aes_init(&ctx, key, nkey);
+
+ cf_ocb_encrypt(&cf_aes, &ctx,
+ plain, nplain,
+ header, nheader,
+ nonce, nnonce,
+ cipher,
+ tag, ntag);
+
+ TEST_CHECK(memcmp(tag, expect_tag, ntag) == 0);
+ TEST_CHECK(memcmp(cipher, expect_cipher, ncipher) == 0);
+
+ uint8_t decrypted[40];
+ int err;
+ err = cf_ocb_decrypt(&cf_aes, &ctx,
+ expect_cipher, ncipher,
+ header, nheader,
+ nonce, nnonce,
+ tag, ntag,
+ decrypted);
+ TEST_CHECK(err == 0);
+ TEST_CHECK(memcmp(decrypted, plain, nplain) == 0);
+
+ tag[0] ^= 0xff;
+
+ err = cf_ocb_decrypt(&cf_aes, &ctx,
+ expect_cipher, ncipher,
+ header, nheader,
+ nonce, nnonce,
+ tag, ntag,
+ decrypted);
+ TEST_CHECK(err == 1);
+}
+
+static void test_ocb(void)
+{
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "", 0,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00", 12,
+ "", 0,
+ "\x78\x54\x07\xBF\xFF\xC8\xAD\x9E\xDC\xC5\x52\x0A\xC9\x11\x1E\xE6", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07", 8,
+ "\x00\x01\x02\x03\x04\x05\x06\x07", 8,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x01", 12,
+ "\x68\x20\xB3\x65\x7B\x6F\x61\x5A", 8,
+ "\x57\x25\xBD\xA0\xD3\xB4\xEB\x3A\x25\x7C\x9A\xF1\xF8\xF0\x30\x09", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07", 8,
+ "", 0,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x02", 12,
+ "", 0,
+ "\x81\x01\x7F\x82\x03\xF0\x81\x27\x71\x52\xFA\xDE\x69\x4A\x0A\x00", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07", 8,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x03", 12,
+ "\x45\xDD\x69\xF8\xF5\xAA\xE7\x24", 8,
+ "\x14\x05\x4C\xD1\xF3\x5D\x82\x76\x0B\x2C\xD0\x0D\x2F\x99\xBF\xA9", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x04", 12,
+ "\x57\x1D\x53\x5B\x60\xB2\x77\x18\x8B\xE5\x14\x71\x70\xA9\xA2\x2C", 16,
+ "\x3A\xD7\xA4\xFF\x38\x35\xB8\xC5\x70\x1C\x1C\xCE\xC8\xFC\x33\x58", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x05", 12,
+ "", 0,
+ "\x8C\xF7\x61\xB6\x90\x2E\xF7\x64\x46\x2A\xD8\x64\x98\xCA\x6B\x97", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x06", 12,
+ "\x5C\xE8\x8E\xC2\xE0\x69\x27\x06\xA9\x15\xC0\x0A\xEB\x8B\x23\x96", 16,
+ "\xF4\x0E\x1C\x74\x3F\x52\x43\x6B\xDF\x06\xD8\xFA\x1E\xCA\x34\x3D", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x07", 12,
+ "\x1C\xA2\x20\x73\x08\xC8\x7C\x01\x07\x56\x10\x4D\x88\x40\xCE\x19\x52\xF0\x96\x73\xA4\x48\xA1\x22", 24,
+ "\xC9\x2C\x62\x24\x10\x51\xF5\x73\x56\xD7\xF3\xC9\x0B\xB0\xE0\x7F", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24,
+ "", 0,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x08", 12,
+ "", 0,
+ "\x6D\xC2\x25\xA0\x71\xFC\x1B\x9F\x7C\x69\xF9\x3B\x0F\x1E\x10\xDE", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17", 24,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x09", 12,
+ "\x22\x1B\xD0\xDE\x7F\xA6\xFE\x99\x3E\xCC\xD7\x69\x46\x0A\x0A\xF2\xD6\xCD\xED\x0C\x39\x5B\x1C\x3C", 24,
+ "\xE7\x25\xF3\x24\x94\xB9\xF9\x14\xD8\x5C\x0B\x1E\xB3\x83\x57\xFF", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\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", 32,
+ "\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", 32,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0A", 12,
+ "\xBD\x6F\x6C\x49\x62\x01\xC6\x92\x96\xC1\x1E\xFD\x13\x8A\x46\x7A\xBD\x3C\x70\x79\x24\xB9\x64\xDE\xAF\xFC\x40\x31\x9A\xF5\xA4\x85", 32,
+ "\x40\xFB\xBA\x18\x6C\x55\x53\xC6\x8A\xD9\xF5\x92\xA7\x9A\x42\x40", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\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", 32,
+ "", 0,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0B", 12,
+ "", 0,
+ "\xFE\x80\x69\x0B\xEE\x8A\x48\x5D\x11\xF3\x29\x65\xBC\x9D\x2A\x32", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "\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", 32,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0C", 12,
+ "\x29\x42\xBF\xC7\x73\xBD\xA2\x3C\xAB\xC6\xAC\xFD\x9B\xFD\x58\x35\xBD\x30\x0F\x09\x73\x79\x2E\xF4\x60\x40\xC5\x3F\x14\x32\xBC\xDF", 32,
+ "\xB5\xE1\xDD\xE3\xBC\x18\xA5\xF8\x40\xB5\x2E\x65\x34\x44\xD5\xDF", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\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\x20\x21\x22\x23\x24\x25\x26\x27", 40,
+ "\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\x20\x21\x22\x23\x24\x25\x26\x27", 40,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0D", 12,
+ "\xD5\xCA\x91\x74\x84\x10\xC1\x75\x1F\xF8\xA2\xF6\x18\x25\x5B\x68\xA0\xA1\x2E\x09\x3F\xF4\x54\x60\x6E\x59\xF9\xC1\xD0\xDD\xC5\x4B\x65\xE8\x62\x8E\x56\x8B\xAD\x7A", 40,
+ "\xED\x07\xBA\x06\xA4\xA6\x94\x83\xA7\x03\x54\x90\xC5\x76\x9E\x60", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "\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\x20\x21\x22\x23\x24\x25\x26\x27", 40,
+ "", 0,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0E", 12,
+ "", 0,
+ "\xC5\xCD\x9D\x18\x50\xC1\x41\xE3\x58\x64\x99\x94\xEE\x70\x1B\x68", 16);
+
+ check_ocb("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16,
+ "", 0,
+ "\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\x20\x21\x22\x23\x24\x25\x26\x27", 40,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0F", 12,
+ "\x44\x12\x92\x34\x93\xC5\x7D\x5D\xE0\xD7\x00\xF7\x53\xCC\xE0\xD1\xD2\xD9\x50\x60\x12\x2E\x9F\x15\xA5\xDD\xBF\xC5\x78\x7E\x50\xB5\xCC\x55\xEE\x50\x7B\xCB\x08\x4E", 40,
+ "\x47\x9A\xD3\x63\xAC\x36\x6B\x95\xA9\x8C\xA5\xF3\x00\x0B\x14\x79", 16);
+
+ check_ocb("\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00", 16,
+ "\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\x20\x21\x22\x23\x24\x25\x26\x27", 40,
+ "\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\x20\x21\x22\x23\x24\x25\x26\x27", 40,
+ "\xBB\xAA\x99\x88\x77\x66\x55\x44\x33\x22\x11\x0D", 12,
+ "\x17\x92\xA4\xE3\x1E\x07\x55\xFB\x03\xE3\x1B\x22\x11\x6E\x6C\x2D\xDF\x9E\xFD\x6E\x33\xD5\x36\xF1\xA0\x12\x4B\x0A\x55\xBA\xE8\x84\xED\x93\x48\x15\x29\xC7\x6B\x6A", 40,
+ "\xD0\xC5\x15\xF4\xD1\xCD\xD4\xFD\xAC\x4F\x02\xAA", 12);
+}
+
+#if !MCU_TARGET
+static void check_ocb_long(size_t nkey, const void *expect_tag, size_t ntag)
+{
+ uint8_t C[22400];
+ uint8_t K[32];
+ uint8_t S[128] = { 0 };
+ uint8_t N[12] = { 0 };
+ size_t nC = 0;
+
+ memset(K, 0, sizeof K);
+ K[nkey - 1] = ntag * 8;
+
+ cf_aes_context aes;
+ cf_aes_init(&aes, K, nkey);
+
+ for (size_t i = 0; i < 128; i++)
+ {
+ /* N = num2str(3i+1, 96) */
+ memset(N, 0, sizeof N);
+ write32_be(3 * i + 1, N + 8);
+
+ /* C = C || OCB-ENCRYPT(K, N, S, S)
+ * nb. OCB-ENCRYPT(Key, Nonce, AAD, Plain) */
+ cf_ocb_encrypt(&cf_aes, &aes,
+ S, i, /* plain */
+ S, i, /* aad */
+ N, sizeof N, /* nonce */
+ C + nC, /* cipher out */
+ C + nC + i, /* tag out */
+ ntag);
+ nC += i + ntag;
+
+ /* N = num2str(3i+2,96) */
+ write32_be(3 * i + 2, N + 8);
+
+ /* C = C || OCB-ENCRYPT(K, N, <empty string>, S) */
+ cf_ocb_encrypt(&cf_aes, &aes,
+ S, i,
+ NULL, 0,
+ N, sizeof N,
+ C + nC,
+ C + nC + i,
+ ntag);
+ nC += i + ntag;
+
+ /* N = num2str(3i+3,96) */
+ write32_be(3 * i + 3, N + 8);
+
+ /* C = C || OCB-ENCRYPT(K, N, S, <empty string>) */
+ cf_ocb_encrypt(&cf_aes, &aes,
+ NULL, 0,
+ S, i,
+ N, sizeof N,
+ NULL,
+ C + nC,
+ ntag);
+ nC += ntag;
+ }
+
+ /* N = num2str(385, 96) */
+ write32_be(385, N + 8);
+
+ /* Output : OCB-ENCRYPT(K, N, C, <empty string>) */
+ uint8_t result[16];
+ cf_ocb_encrypt(&cf_aes, &aes,
+ NULL, 0,
+ C, nC,
+ N, sizeof N,
+ NULL,
+ result, ntag);
+
+ TEST_CHECK(memcmp(result, expect_tag, ntag) == 0);
+}
+
+static void test_ocb_long(void)
+{
+ check_ocb_long(16, "\x67\xE9\x44\xD2\x32\x56\xC5\xE0\xB6\xC6\x1F\xA2\x2F\xDF\x1E\xA2", 16);
+ check_ocb_long(24, "\xF6\x73\xF2\xC3\xE7\x17\x4A\xAE\x7B\xAE\x98\x6C\xA9\xF2\x9E\x17", 16);
+ check_ocb_long(32, "\xD9\x0E\xB8\xE9\xC9\x77\xC8\x8B\x79\xDD\x79\x3D\x7F\xFA\x16\x1C", 16);
+ check_ocb_long(16, "\x77\xA3\xD8\xE7\x35\x89\x15\x8D\x25\xD0\x12\x09", 12);
+ check_ocb_long(24, "\x05\xD5\x6E\xAD\x27\x52\xC8\x6B\xE6\x93\x2C\x5E", 12);
+ check_ocb_long(32, "\x54\x58\x35\x9A\xC2\x3B\x0C\xBA\x9E\x63\x30\xDD", 12);
+ check_ocb_long(16, "\x19\x2C\x9B\x7B\xD9\x0B\xA0\x6A", 8);
+ check_ocb_long(24, "\x00\x66\xBC\x6E\x0E\xF3\x4E\x24", 8);
+ check_ocb_long(32, "\x7D\x4E\xA5\xD4\x45\x50\x1C\xBE", 8);
+}
+#endif
+
+TEST_LIST = {
+ { "cbc", test_cbc },
+ { "cbcmac", test_cbcmac },
+ { "ctr", test_ctr },
+ { "eax", test_eax },
+ { "cmac", test_cmac },
+ { "gf128-mul", test_gf128_mul },
+ { "gcm", test_gcm },
+ { "ccm", test_ccm },
+ { "ocb", test_ocb },
+ /* These remaining tests are too big for microcontroller targets. */
+#if !MCU_TARGET
+ { "ccm-long", test_ccm_long },
+ { "ocb-long", test_ocb_long },
+#endif
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.c
new file mode 100644
index 00000000..b18393f5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.c
@@ -0,0 +1,118 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "norx.h"
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+static void test_vector(void)
+{
+ uint8_t K[16], N[8], A[128], M[128], Z[128], C[128], T[16];
+
+ /* This is from the v2.0 paper, section A.2. */
+
+ unhex(K, sizeof K, "000102030405060708090a0b0c0d0e0f");
+ unhex(N, sizeof N, "f0e0d0c0b0a09080");
+
+ for (unsigned i = 0; i < 128; i++)
+ {
+ A[i] = M[i] = Z[i] = i;
+ }
+
+ cf_norx32_encrypt(K, N,
+ A, sizeof A,
+ M, sizeof M,
+ Z, sizeof Z,
+ C, T);
+
+ uint8_t expect_C[128], expect_T[16];
+
+ unhex(expect_C, sizeof expect_C, "f4afc8e66d2d80de0a7f719c899624c9ad896ec7c61739d5376d0648c7bcb204e57db05c6f83b3ff4315e8a4ef2f2c855f21ea4c51ac6de575773ba548f36e636a13b979d953bb91298ea4a6e2aa27402991e0da541997825407b2f12441de3ae6c5dbfe41b12f1480d234832765111e4c09deef9fe3971618d2217c4b77921e");
+ unhex(expect_T, sizeof expect_T, "7810131eea2eab1e5da05d23d4e3cb99");
+
+ TEST_CHECK(memcmp(C, expect_C, sizeof C) == 0);
+ TEST_CHECK(memcmp(T, expect_T, sizeof T) == 0);
+
+ uint8_t M2[128];
+ TEST_CHECK(0 ==
+ cf_norx32_decrypt(K, N,
+ A, sizeof A,
+ C, sizeof C,
+ Z, sizeof Z,
+ T,
+ M2));
+
+ TEST_CHECK(memcmp(M, M2, sizeof M) == 0);
+ T[0] ^= 0xff;
+
+ TEST_CHECK(cf_norx32_decrypt(K, N,
+ A, sizeof A,
+ C, sizeof C,
+ Z, sizeof Z,
+ T,
+ M2));
+}
+
+#include "testnorx.katdata.inc"
+
+static void test_kat(void)
+{
+ uint8_t K[16], N[16], H[256], W[256];
+ const uint8_t *kats = kat_data;
+
+#define FILL(arr, c) \
+ do { \
+ for (size_t i = 0; i < sizeof arr; i++) \
+ arr[i] = (i * c + 123) & 0xff; \
+ } while (0)
+ FILL(N, 181);
+ FILL(K, 191);
+ FILL(H, 193);
+ FILL(W, 197);
+#undef FILL
+
+ for (size_t i = 0; i < sizeof W; i++)
+ {
+ uint8_t C[256];
+ uint8_t A[16];
+
+ cf_norx32_encrypt(K, N,
+ H, i,
+ W, i,
+ NULL, 0,
+ C, A);
+
+ TEST_CHECK(memcmp(kats, C, i) == 0);
+ kats += i;
+ TEST_CHECK(memcmp(kats, A, sizeof A) == 0);
+ kats += sizeof A;
+
+ uint8_t M[256] = { 0 };
+ TEST_CHECK(0 == cf_norx32_decrypt(K, N,
+ H, i,
+ C, i,
+ NULL, 0,
+ A, M));
+
+ TEST_CHECK(0 == memcmp(M, W, i));
+ }
+}
+
+TEST_LIST = {
+ { "vector", test_vector },
+ { "kat", test_kat },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc
new file mode 100644
index 00000000..13dd7461
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testnorx.katdata.inc
@@ -0,0 +1,4961 @@
+static const uint8_t kat_data[] = {
+ 0xAF, 0x7C, 0xEF, 0x63, 0x5D, 0xEE, 0x94, 0x74,
+ 0x9B, 0xC2, 0x03, 0x9E, 0xC0, 0x49, 0xE0, 0x81,
+
+ 0x69, 0x63, 0x57, 0x72, 0xEC, 0x0B, 0x66, 0xF2,
+ 0xE4, 0xB0, 0x1D, 0x30, 0x34, 0x29, 0x84, 0xE9,
+ 0xA8,
+
+ 0x02, 0x46, 0x13, 0xCC, 0x6B, 0x19, 0x96, 0xB3,
+ 0x7E, 0x1C, 0xA6, 0x79, 0x00, 0x28, 0x19, 0x09,
+ 0x9F, 0x86,
+
+ 0x99, 0xAC, 0xEA, 0x8C, 0x2B, 0x70, 0x02, 0xBA,
+ 0x86, 0xE9, 0xEB, 0x22, 0xEC, 0x23, 0xAF, 0x9A,
+ 0x95, 0xD0, 0xE5,
+
+ 0xFE, 0xFB, 0xA0, 0xBA, 0x20, 0x28, 0x50, 0xDC,
+ 0xE5, 0xD6, 0x70, 0x26, 0x7A, 0x9E, 0x2A, 0xC3,
+ 0x3F, 0xCB, 0xD7, 0x0C,
+
+ 0xB9, 0x67, 0x98, 0x4F, 0xDF, 0x1B, 0x19, 0x66,
+ 0x9C, 0xDE, 0xAE, 0x96, 0x76, 0xDB, 0xDE, 0x55,
+ 0x95, 0x50, 0xD9, 0xC2, 0xBA,
+
+ 0x62, 0x28, 0x9A, 0x03, 0xF3, 0xF2, 0xFB, 0x0E,
+ 0xCF, 0xD4, 0x11, 0x74, 0x1D, 0x8E, 0x8B, 0xCD,
+ 0x92, 0x52, 0x96, 0x5B, 0x64, 0x99,
+
+ 0x2F, 0xCE, 0xB4, 0x86, 0x4C, 0x0A, 0x47, 0xEB,
+ 0x98, 0x2A, 0xD2, 0xA1, 0x59, 0x9A, 0x5A, 0xB9,
+ 0x0C, 0xA7, 0x7D, 0xB0, 0xA6, 0xFF, 0x05,
+
+ 0xE0, 0x22, 0x71, 0xE2, 0xCD, 0xF8, 0x3C, 0x12,
+ 0x8B, 0x4E, 0x28, 0x14, 0x6F, 0x0E, 0x18, 0xAE,
+ 0x23, 0xDF, 0xD0, 0x59, 0x70, 0x9E, 0x54, 0x49,
+
+ 0xF6, 0xB6, 0x9E, 0x08, 0xB8, 0x27, 0x54, 0x94,
+ 0xD1, 0x0B, 0x93, 0x25, 0xEF, 0xD5, 0xE2, 0x19,
+ 0xEF, 0xEA, 0x0C, 0xFC, 0x01, 0x75, 0xC2, 0x90,
+ 0x00,
+
+ 0x54, 0xBE, 0x7D, 0xFB, 0xF5, 0xCC, 0x52, 0xC6,
+ 0x9A, 0x0F, 0x65, 0xBD, 0xF1, 0x53, 0x5D, 0x01,
+ 0x07, 0xCC, 0xAB, 0xB9, 0xA5, 0x53, 0xFD, 0xE7,
+ 0xE4, 0x74,
+
+ 0xD7, 0x6E, 0x5B, 0x87, 0xD0, 0xC1, 0x68, 0x92,
+ 0xD0, 0x80, 0x7D, 0x36, 0x8D, 0xE7, 0x36, 0xC5,
+ 0x97, 0xE7, 0x46, 0xDA, 0xC9, 0x19, 0xD9, 0x98,
+ 0xD9, 0xBD, 0x7B,
+
+ 0x7E, 0xEB, 0x69, 0xAB, 0x77, 0x97, 0xDA, 0xE8,
+ 0x47, 0xA4, 0x6E, 0x4A, 0x1D, 0xC9, 0x00, 0xF3,
+ 0x4B, 0x2E, 0xCD, 0x56, 0xDF, 0xE1, 0xAF, 0x9E,
+ 0xE8, 0xAD, 0x94, 0x48,
+
+ 0xDF, 0xAB, 0x2B, 0xE7, 0x84, 0x9C, 0xBB, 0x96,
+ 0x3F, 0x02, 0x99, 0x65, 0x42, 0x1A, 0x0D, 0x33,
+ 0x97, 0xA8, 0x23, 0x7C, 0x59, 0x4E, 0xCC, 0x64,
+ 0x54, 0x11, 0x6F, 0x09, 0x80,
+
+ 0xB5, 0x4B, 0x1A, 0x8C, 0x05, 0x62, 0x60, 0x7A,
+ 0xCC, 0xA8, 0x63, 0x7F, 0xCC, 0xC6, 0x13, 0x70,
+ 0xF8, 0xC6, 0x09, 0x5C, 0x45, 0x93, 0x3E, 0x7C,
+ 0x9E, 0x27, 0x23, 0x42, 0xAE, 0x52,
+
+ 0x56, 0x3E, 0x38, 0xC7, 0x66, 0xCE, 0xB5, 0x8F,
+ 0x77, 0xA1, 0x20, 0xE2, 0x69, 0x08, 0x92, 0x1E,
+ 0x32, 0x01, 0x75, 0xD2, 0x05, 0x92, 0x1B, 0x60,
+ 0x60, 0x9F, 0xD2, 0xA3, 0x89, 0x49, 0x6E,
+
+ 0x01, 0x91, 0x5D, 0xDC, 0xC7, 0xB1, 0x4F, 0x6D,
+ 0x73, 0x4D, 0x3B, 0x68, 0xA0, 0xA5, 0x1D, 0xA5,
+ 0x22, 0x3C, 0xFE, 0xDC, 0x86, 0xB1, 0x64, 0x54,
+ 0x92, 0xE1, 0x0F, 0x32, 0xD5, 0xA6, 0x4B, 0xAC,
+
+ 0x13, 0xF8, 0xFC, 0xDB, 0x41, 0x62, 0x9F, 0x6E,
+ 0xE6, 0x9B, 0xAB, 0xE5, 0x27, 0x3B, 0x8C, 0x15,
+ 0x8C, 0xC8, 0x03, 0x38, 0xE3, 0x7E, 0x83, 0xDA,
+ 0xA2, 0x5B, 0xA8, 0x44, 0xE2, 0x41, 0x47, 0x53,
+ 0x2A,
+
+ 0xD2, 0x73, 0x87, 0xC2, 0xF0, 0x28, 0x2A, 0x0F,
+ 0xE6, 0x37, 0xC9, 0xAF, 0xF3, 0x02, 0xAC, 0xEA,
+ 0x37, 0xB6, 0x8C, 0xA6, 0x37, 0x5F, 0x79, 0x89,
+ 0xCD, 0x90, 0x6B, 0xCC, 0xF6, 0x7C, 0xEC, 0xD9,
+ 0x75, 0xE6,
+
+ 0x0B, 0x76, 0x2F, 0xAC, 0x9F, 0x20, 0xA1, 0x56,
+ 0x5F, 0xF9, 0x67, 0xB8, 0xDC, 0xAC, 0x48, 0xA0,
+ 0x00, 0xD3, 0xFE, 0x87, 0xAE, 0x13, 0x07, 0x26,
+ 0xD9, 0xC2, 0x6D, 0xF9, 0xEC, 0xB4, 0xA2, 0x41,
+ 0x17, 0xB6, 0x4C,
+
+ 0xA2, 0xE6, 0x67, 0xBC, 0x65, 0x03, 0x88, 0xDC,
+ 0xAD, 0x8B, 0x3C, 0x28, 0x83, 0x5F, 0xE3, 0x47,
+ 0x95, 0xDA, 0xF9, 0x6A, 0x09, 0xE9, 0xF9, 0xD5,
+ 0x58, 0xE4, 0xC3, 0x64, 0x3E, 0xE2, 0x82, 0x22,
+ 0xC3, 0xF7, 0x50, 0x40,
+
+ 0x73, 0xA2, 0xA1, 0xB7, 0xC4, 0xCC, 0x5F, 0xA6,
+ 0x86, 0x7A, 0xFB, 0xF9, 0x2D, 0xB0, 0x92, 0x90,
+ 0xDB, 0xD1, 0xD0, 0xD4, 0x7E, 0x83, 0xD8, 0xF7,
+ 0x39, 0x38, 0xFA, 0xD4, 0x24, 0x56, 0x96, 0x1D,
+ 0xF5, 0xB9, 0x35, 0x7A, 0x7B,
+
+ 0xCB, 0xA1, 0x1C, 0x70, 0x7E, 0x42, 0xF7, 0x32,
+ 0x68, 0x56, 0x27, 0xC7, 0xFD, 0x13, 0xCE, 0xC2,
+ 0xD3, 0xEE, 0x3E, 0x33, 0xF3, 0xC3, 0xB4, 0x87,
+ 0x31, 0x6E, 0xDA, 0xA1, 0x09, 0x77, 0x9E, 0xBE,
+ 0x43, 0x8D, 0x11, 0xF9, 0x0B, 0x5B,
+
+ 0x31, 0xD7, 0x0C, 0xE3, 0xD3, 0x37, 0xCA, 0xF9,
+ 0x9E, 0x7E, 0x57, 0xF1, 0x45, 0x02, 0x7D, 0xDC,
+ 0xA9, 0xBF, 0x73, 0x6B, 0x04, 0x16, 0x44, 0x6D,
+ 0x62, 0x65, 0x2E, 0x5D, 0xBE, 0x75, 0xD0, 0xA2,
+ 0x88, 0xF2, 0x60, 0xFE, 0x7B, 0xED, 0x74,
+
+ 0x42, 0xD4, 0xAD, 0xFF, 0xDB, 0x5D, 0xBF, 0x2F,
+ 0xA9, 0xE1, 0x7B, 0x60, 0xB8, 0xE8, 0x4D, 0x6F,
+ 0xF9, 0x70, 0xE4, 0x26, 0x40, 0xFA, 0x19, 0x36,
+ 0x07, 0x5C, 0xEA, 0x0F, 0x47, 0x89, 0xE0, 0x91,
+ 0xD2, 0xF7, 0x75, 0xB7, 0x27, 0x3A, 0xCC, 0xEB,
+
+ 0xCB, 0x20, 0xDD, 0xCD, 0x30, 0x13, 0xD8, 0x84,
+ 0xD8, 0x57, 0xAA, 0xFA, 0x74, 0xDA, 0x46, 0x49,
+ 0x35, 0x60, 0x93, 0x20, 0xAB, 0x32, 0x19, 0x02,
+ 0x3C, 0x8F, 0x9F, 0x1E, 0xAD, 0x4B, 0x8F, 0x5A,
+ 0xE5, 0x1F, 0xEA, 0x8B, 0x5C, 0x53, 0x81, 0x68,
+ 0x0D,
+
+ 0xF9, 0x00, 0x75, 0x76, 0x0E, 0x8B, 0x33, 0xAF,
+ 0x83, 0xD4, 0xB4, 0x0D, 0xF1, 0x48, 0xD5, 0x02,
+ 0x08, 0x6F, 0xEC, 0x1B, 0xB0, 0x40, 0x82, 0xF2,
+ 0xF4, 0x52, 0xCB, 0x43, 0xE6, 0x0F, 0x1F, 0xBE,
+ 0x15, 0xCE, 0x9D, 0xB8, 0xED, 0x3F, 0x7B, 0xD0,
+ 0x94, 0xFF,
+
+ 0x6C, 0x78, 0x7D, 0x34, 0x07, 0xA5, 0xB2, 0xA9,
+ 0xF8, 0x8F, 0xB6, 0x4E, 0x0D, 0x31, 0x23, 0xD2,
+ 0x71, 0xB5, 0x7D, 0x10, 0xBA, 0xA7, 0x35, 0x1F,
+ 0xDE, 0x10, 0xE7, 0x21, 0x56, 0x50, 0xB1, 0xAD,
+ 0x76, 0x03, 0x7C, 0x8C, 0x88, 0x12, 0x09, 0x46,
+ 0xF4, 0x5F, 0x57,
+
+ 0xFC, 0xAC, 0x41, 0xB1, 0x66, 0xBD, 0xFE, 0x96,
+ 0x4D, 0xDA, 0x18, 0x9C, 0xDA, 0xA8, 0xC7, 0x6A,
+ 0x94, 0x5D, 0x2B, 0x44, 0xB0, 0xF6, 0x89, 0x58,
+ 0x9C, 0x30, 0xD3, 0xC8, 0x48, 0x2F, 0xE8, 0x9F,
+ 0xB5, 0x33, 0x4C, 0x2A, 0x89, 0x15, 0x71, 0xDF,
+ 0xDB, 0xA0, 0x4B, 0x00,
+
+ 0x1F, 0x85, 0x54, 0x96, 0x15, 0x04, 0x80, 0x09,
+ 0xDB, 0x13, 0xA7, 0x52, 0x03, 0x5F, 0x8C, 0x6E,
+ 0x66, 0x9D, 0x65, 0x64, 0xB0, 0x73, 0xC0, 0x61,
+ 0xCD, 0xF1, 0xEF, 0xE6, 0x01, 0x5B, 0x3B, 0x85,
+ 0xB8, 0x9E, 0x54, 0xC8, 0x47, 0x9C, 0x8A, 0x9C,
+ 0x27, 0x43, 0x4D, 0xB3, 0x33,
+
+ 0x96, 0xEA, 0xF6, 0x72, 0xED, 0x28, 0x75, 0x42,
+ 0x06, 0x81, 0xEA, 0x29, 0xDF, 0xE4, 0x06, 0x51,
+ 0xD2, 0x3F, 0x42, 0xF5, 0x9C, 0xDD, 0x4C, 0xCD,
+ 0xA3, 0xEC, 0x46, 0x65, 0xD8, 0xA2, 0x5D, 0x05,
+ 0x6D, 0x5B, 0x46, 0x18, 0x44, 0xB0, 0x34, 0x02,
+ 0x7A, 0xEF, 0x24, 0x2A, 0x73, 0x69,
+
+ 0x41, 0xC9, 0xA4, 0x8C, 0xE0, 0x92, 0xB4, 0xAB,
+ 0xCB, 0xFA, 0x94, 0xDF, 0xF5, 0x29, 0xFA, 0x23,
+ 0x43, 0x0F, 0xF0, 0x96, 0x01, 0x58, 0xAC, 0x6E,
+ 0x16, 0x5B, 0x59, 0xAA, 0x46, 0x10, 0xA5, 0x27,
+ 0xF3, 0xD0, 0x6D, 0x7B, 0xA8, 0x44, 0x2E, 0x9D,
+ 0xF9, 0x62, 0x87, 0xA4, 0xA2, 0xDC, 0x69,
+
+ 0xA6, 0xBB, 0x70, 0x33, 0x8E, 0x2E, 0xBD, 0xF7,
+ 0x24, 0xAF, 0x04, 0xAF, 0x33, 0x3C, 0x58, 0x6A,
+ 0xB0, 0x83, 0xC6, 0x4B, 0xE6, 0xB6, 0x90, 0xDA,
+ 0x29, 0xFC, 0x34, 0xDE, 0x50, 0x4E, 0x4F, 0x77,
+ 0xD6, 0x31, 0x41, 0x80, 0x52, 0x06, 0x39, 0x11,
+ 0x83, 0xA9, 0x34, 0x69, 0x87, 0xAC, 0x54, 0x28,
+
+ 0x5E, 0x8D, 0x7B, 0xAE, 0xCD, 0x3B, 0x76, 0xBC,
+ 0xD6, 0x0A, 0x5D, 0x7A, 0x91, 0x4C, 0x51, 0x5D,
+ 0x54, 0xA6, 0x9D, 0xB8, 0xAD, 0xE9, 0xA3, 0xCB,
+ 0x80, 0xAD, 0xE8, 0x72, 0x99, 0xFE, 0x31, 0xFA,
+ 0x9F, 0x5E, 0xB4, 0x7A, 0x8A, 0x33, 0x19, 0x42,
+ 0xF4, 0x7E, 0xB1, 0x68, 0x28, 0x72, 0xFD, 0xCB,
+ 0x39,
+
+ 0x4E, 0x1D, 0xFC, 0x0C, 0x9C, 0x55, 0x80, 0x6A,
+ 0x05, 0x1B, 0x55, 0x77, 0x9D, 0x42, 0x98, 0x4A,
+ 0x70, 0x70, 0x1E, 0x06, 0x48, 0xD3, 0x76, 0x72,
+ 0x6A, 0x14, 0x71, 0xA2, 0xF9, 0xB1, 0xB2, 0xE9,
+ 0x17, 0x08, 0x95, 0x20, 0x2A, 0x00, 0xDF, 0x29,
+ 0x3B, 0xFA, 0x3C, 0xD2, 0x63, 0xAF, 0x24, 0xF9,
+ 0x08, 0x09,
+
+ 0xCB, 0x1E, 0x1E, 0x95, 0xE6, 0x40, 0xDF, 0x3F,
+ 0x0C, 0x7B, 0x5B, 0x76, 0xFD, 0x13, 0xC4, 0x95,
+ 0xBE, 0xCC, 0x66, 0xD9, 0x1D, 0x4F, 0xBD, 0x29,
+ 0xBB, 0x3F, 0x5C, 0x3B, 0xA4, 0x0E, 0x4E, 0x76,
+ 0xD4, 0x42, 0x6F, 0x64, 0xCA, 0x26, 0xAB, 0x7B,
+ 0xA6, 0x9C, 0x54, 0x7B, 0x2A, 0x71, 0xBA, 0xC2,
+ 0xF0, 0xF2, 0x6F,
+
+ 0x63, 0xF4, 0x8B, 0x62, 0x4F, 0xE7, 0x46, 0xCC,
+ 0x4F, 0x60, 0x20, 0x8B, 0x00, 0x57, 0xD0, 0xA7,
+ 0xDF, 0x6F, 0x08, 0x5C, 0x6F, 0x00, 0x78, 0xA8,
+ 0x5A, 0x77, 0x71, 0x65, 0x6E, 0x01, 0x71, 0x8D,
+ 0x2B, 0x15, 0x90, 0x7E, 0x59, 0xA4, 0xF6, 0x23,
+ 0xF3, 0x12, 0xBC, 0x3C, 0xFD, 0x21, 0x7D, 0x2E,
+ 0x7E, 0x4F, 0x83, 0xD7,
+
+ 0x76, 0xC1, 0x46, 0xC5, 0x86, 0x11, 0xE9, 0x28,
+ 0x6A, 0x97, 0x26, 0xC7, 0x89, 0xA7, 0xCD, 0x01,
+ 0x40, 0x53, 0xD6, 0x42, 0xB3, 0xF1, 0x48, 0x51,
+ 0x11, 0xC6, 0x9E, 0xDF, 0x91, 0x5C, 0xD9, 0x4C,
+ 0xB9, 0x68, 0x63, 0x6D, 0xBC, 0xCE, 0x6F, 0x5E,
+ 0xE3, 0xFC, 0xAB, 0xCE, 0x24, 0x94, 0x5C, 0x43,
+ 0x51, 0xB6, 0xE7, 0x99, 0x45,
+
+ 0xC9, 0xC7, 0xCD, 0x1F, 0x2E, 0x48, 0x25, 0xC3,
+ 0x1C, 0xF8, 0x85, 0x32, 0x15, 0x56, 0x82, 0x17,
+ 0xF4, 0xDC, 0x5F, 0xAE, 0xEF, 0x94, 0xDD, 0xFA,
+ 0xEA, 0xEE, 0xFC, 0x9B, 0x8C, 0xE1, 0x2E, 0xCF,
+ 0xE3, 0x40, 0x03, 0xF7, 0xBD, 0x7B, 0x12, 0x56,
+ 0x42, 0xCA, 0x1A, 0x68, 0xEF, 0xC3, 0xEF, 0xAC,
+ 0xEB, 0xA8, 0xD8, 0x91, 0x8C, 0x42,
+
+ 0x78, 0xF9, 0x51, 0x9E, 0x84, 0x32, 0xFC, 0xBA,
+ 0x46, 0xA0, 0xF1, 0x04, 0x77, 0xF6, 0x93, 0xAD,
+ 0xB3, 0x95, 0xA3, 0x69, 0xA4, 0xAD, 0x45, 0x89,
+ 0x39, 0xFC, 0x08, 0x35, 0x45, 0xA9, 0xDC, 0x26,
+ 0x55, 0xA2, 0x8E, 0x3E, 0xF5, 0xE3, 0x86, 0xD1,
+ 0x1A, 0x37, 0x4C, 0x96, 0x16, 0x68, 0x06, 0x01,
+ 0xF0, 0x0D, 0x02, 0x4F, 0x17, 0x34, 0x9C,
+
+ 0xD8, 0xFF, 0x53, 0x2C, 0xEE, 0xA5, 0xEB, 0x21,
+ 0xD8, 0x4C, 0x89, 0xCF, 0x7F, 0x15, 0x59, 0x5D,
+ 0xDD, 0x45, 0x01, 0x6A, 0x71, 0x0B, 0x47, 0x2C,
+ 0x72, 0x08, 0xC4, 0x5D, 0x71, 0x6A, 0x59, 0xDB,
+ 0x46, 0x0E, 0xDF, 0xD7, 0x2B, 0xDA, 0xE1, 0x69,
+ 0x0A, 0xE7, 0xD7, 0x5F, 0x18, 0x49, 0xC6, 0xA2,
+ 0xA7, 0x1A, 0x2E, 0x94, 0xCD, 0x45, 0xD9, 0x5A,
+
+ 0x51, 0x54, 0x80, 0x8F, 0x07, 0xDA, 0xCC, 0x7B,
+ 0xB8, 0xE1, 0xE0, 0xEE, 0xF2, 0x7D, 0x8D, 0x2D,
+ 0xF0, 0x50, 0x5A, 0xB6, 0xF5, 0xBC, 0x62, 0xBC,
+ 0xA6, 0x75, 0xB7, 0x80, 0xBA, 0x6E, 0x1D, 0x7C,
+ 0xD5, 0xC7, 0x42, 0x31, 0xA3, 0x98, 0x08, 0xFE,
+ 0x13, 0xA2, 0xA6, 0x74, 0x4D, 0xF3, 0x20, 0x9E,
+ 0xEB, 0x83, 0x64, 0x27, 0xE4, 0x9C, 0x3C, 0x1F,
+ 0xC2,
+
+ 0xF1, 0x24, 0xBC, 0xD3, 0x95, 0x66, 0x65, 0x69,
+ 0xA7, 0x6E, 0x61, 0x08, 0x9C, 0xBF, 0xC3, 0x9B,
+ 0x9B, 0x09, 0x05, 0x0B, 0x94, 0xB4, 0x64, 0xB2,
+ 0x0E, 0x0F, 0x19, 0x0C, 0x6D, 0x92, 0xF5, 0xC3,
+ 0xB8, 0x9B, 0xBF, 0x59, 0x00, 0x6D, 0x8D, 0x48,
+ 0xE0, 0xB1, 0x06, 0xC2, 0x3E, 0x33, 0x26, 0x24,
+ 0x6F, 0x53, 0xBE, 0x86, 0xD7, 0xEA, 0xCD, 0x18,
+ 0x18, 0x24,
+
+ 0xE8, 0xE1, 0xC4, 0x50, 0xEF, 0xB6, 0xF0, 0xCA,
+ 0x78, 0xEF, 0x9C, 0x51, 0x61, 0x58, 0x18, 0xB7,
+ 0x90, 0x09, 0x48, 0x73, 0xA1, 0x13, 0x6D, 0x16,
+ 0x8D, 0x97, 0x84, 0x92, 0x25, 0x44, 0xBF, 0xF5,
+ 0x3C, 0x9D, 0xCE, 0x68, 0x7E, 0x4B, 0x0A, 0x49,
+ 0xE1, 0xAE, 0xA7, 0xB3, 0xC8, 0xE0, 0x7B, 0x54,
+ 0xF9, 0xAB, 0x22, 0x0A, 0x19, 0x4F, 0x86, 0x1F,
+ 0xB7, 0x0F, 0x3A,
+
+ 0x23, 0xD4, 0x95, 0xC7, 0xF9, 0xB7, 0x17, 0x4B,
+ 0xE8, 0x10, 0xF9, 0xB4, 0xCA, 0x9F, 0xBA, 0xBE,
+ 0x66, 0xAA, 0x83, 0x98, 0x7D, 0x2B, 0xF4, 0x84,
+ 0x18, 0x13, 0xCE, 0xBE, 0x10, 0x7D, 0x1B, 0x76,
+ 0x89, 0xBC, 0x9C, 0xF4, 0xE6, 0x71, 0x62, 0xA7,
+ 0x39, 0x89, 0xEF, 0x0D, 0xE9, 0x63, 0xD9, 0xB1,
+ 0x96, 0x63, 0xAC, 0xBC, 0xC7, 0x85, 0x77, 0xE3,
+ 0xD4, 0x40, 0x41, 0x5C,
+
+ 0x0F, 0x8F, 0x47, 0xF8, 0xEA, 0x17, 0x30, 0x7E,
+ 0x67, 0xE2, 0x69, 0xF5, 0x20, 0xD9, 0xE0, 0x87,
+ 0xAB, 0xF6, 0x70, 0xBE, 0xF1, 0x26, 0x25, 0x01,
+ 0x14, 0x69, 0xE8, 0x8E, 0xA9, 0x8E, 0xB2, 0xAE,
+ 0xA5, 0x2C, 0x5F, 0x9D, 0x0C, 0x50, 0xC6, 0x95,
+ 0xC1, 0xDE, 0xEC, 0x7D, 0xEA, 0x87, 0xCA, 0x02,
+ 0xD7, 0x3F, 0x5E, 0x8A, 0xB3, 0x3A, 0xDA, 0x6A,
+ 0x33, 0xAD, 0x06, 0xD4, 0x6D,
+
+ 0xAB, 0x89, 0xF3, 0x78, 0x67, 0x63, 0xD5, 0xFC,
+ 0xF2, 0x19, 0xD5, 0x91, 0x5C, 0x10, 0x86, 0x9F,
+ 0xD2, 0xDC, 0x46, 0xD9, 0xC7, 0xAA, 0x4E, 0x44,
+ 0xFF, 0x79, 0x5B, 0x8A, 0xE3, 0x47, 0x92, 0x20,
+ 0xA8, 0xA3, 0x5C, 0x95, 0xEF, 0xD2, 0x21, 0x49,
+ 0x8C, 0x66, 0x0D, 0xCD, 0xD2, 0x1D, 0x11, 0x22,
+ 0x31, 0x62, 0x47, 0xC9, 0xD4, 0xC1, 0xBC, 0xB3,
+ 0x80, 0x84, 0xB4, 0x71, 0xC1, 0xAB,
+
+ 0x85, 0x76, 0x7F, 0x0D, 0x73, 0xE2, 0x6C, 0xB5,
+ 0x98, 0x1F, 0x7E, 0x09, 0xFC, 0x2D, 0xD6, 0xA4,
+ 0xE7, 0x57, 0xDC, 0x14, 0xCB, 0xD9, 0x7D, 0x46,
+ 0xC9, 0x6E, 0xE7, 0x61, 0x0A, 0x5F, 0x3D, 0xAB,
+ 0x4D, 0x39, 0x77, 0x96, 0xF5, 0xB0, 0x0C, 0x53,
+ 0x21, 0xBB, 0xA2, 0xAC, 0xA9, 0xC6, 0x91, 0xB9,
+ 0xF8, 0x03, 0xE2, 0xDD, 0xEE, 0x3B, 0xB7, 0xEB,
+ 0xD8, 0xB7, 0xCE, 0xAC, 0x02, 0xA1, 0xA8,
+
+ 0xAA, 0xBE, 0xDD, 0x59, 0x61, 0xF8, 0xD1, 0x11,
+ 0x7A, 0xC2, 0x81, 0x7E, 0x61, 0x58, 0xAF, 0xA2,
+ 0x67, 0xC1, 0xA2, 0x8F, 0xE1, 0xC7, 0x0D, 0x27,
+ 0x2B, 0x4A, 0x9A, 0x6A, 0x77, 0x68, 0xFD, 0x68,
+ 0x18, 0xF1, 0xDB, 0x55, 0xBA, 0xEC, 0x2A, 0x37,
+ 0x7F, 0xD2, 0x68, 0xA7, 0xEF, 0x31, 0x77, 0x97,
+ 0xDE, 0x6B, 0x56, 0xB1, 0x5E, 0xBE, 0xBD, 0x51,
+ 0x07, 0x3E, 0xD6, 0xD9, 0x01, 0x64, 0xB8, 0x65,
+
+ 0x52, 0x67, 0x5D, 0x5E, 0x11, 0xDA, 0x06, 0xC2,
+ 0xA6, 0x8E, 0x41, 0xE4, 0x30, 0x59, 0x2F, 0x73,
+ 0x40, 0x03, 0x88, 0x85, 0xE6, 0x91, 0x29, 0xCB,
+ 0xA6, 0x68, 0x56, 0xCF, 0x05, 0xE4, 0xD7, 0xA2,
+ 0x46, 0xC6, 0xC1, 0x06, 0x50, 0x0E, 0x1F, 0xAA,
+ 0xC2, 0xB2, 0x6E, 0x2F, 0xB9, 0x1A, 0x9F, 0xC3,
+ 0xC0, 0xD8, 0xD7, 0xF6, 0xCD, 0xD8, 0x92, 0xFB,
+ 0x6A, 0x4F, 0xFA, 0x2D, 0x0E, 0x13, 0x01, 0xD8,
+ 0x9A,
+
+ 0x6B, 0xA5, 0xF2, 0x8D, 0x73, 0x10, 0x6F, 0x06,
+ 0x2B, 0x8B, 0x10, 0x56, 0xF6, 0x5F, 0xC0, 0x94,
+ 0x1C, 0x70, 0xB3, 0xBE, 0xEE, 0x00, 0x4D, 0x50,
+ 0x94, 0x88, 0xC5, 0x51, 0x01, 0x8B, 0xE8, 0xA5,
+ 0xF8, 0x89, 0x0F, 0x97, 0x7F, 0x0C, 0x67, 0x6F,
+ 0xC7, 0x1F, 0x91, 0x20, 0xD7, 0x32, 0x9C, 0x63,
+ 0xFF, 0xE7, 0xB8, 0x63, 0x0F, 0xE1, 0xCE, 0xC7,
+ 0xEA, 0x82, 0x1D, 0x57, 0xEC, 0xB9, 0xF9, 0x05,
+ 0x8D, 0x94,
+
+ 0xFE, 0x5B, 0xB2, 0x66, 0xD8, 0xDF, 0x19, 0x49,
+ 0x59, 0x8E, 0xBC, 0xC5, 0xC7, 0xD1, 0x6F, 0x0A,
+ 0x8A, 0x5B, 0x0C, 0xF4, 0xC2, 0x35, 0x62, 0x61,
+ 0x89, 0x2E, 0x43, 0x70, 0x7D, 0x5A, 0xE7, 0xF1,
+ 0x63, 0x92, 0xDD, 0xD4, 0xBD, 0x61, 0x93, 0x8C,
+ 0x21, 0x13, 0x96, 0xBA, 0xDB, 0x7A, 0x1B, 0x81,
+ 0x43, 0x6B, 0x3F, 0x2C, 0x2E, 0x6B, 0xB2, 0x49,
+ 0x2E, 0x28, 0xB2, 0x79, 0x52, 0x66, 0x89, 0x48,
+ 0xE7, 0x97, 0x44,
+
+ 0x4C, 0xAD, 0x82, 0xE3, 0x09, 0xEA, 0x08, 0x73,
+ 0xF4, 0x16, 0x4D, 0x67, 0x33, 0x17, 0xB0, 0x47,
+ 0x16, 0xA2, 0xAF, 0x99, 0xFE, 0x5A, 0x45, 0x70,
+ 0x5C, 0xB2, 0xF2, 0x7A, 0x64, 0xC9, 0x65, 0xE3,
+ 0x07, 0xAD, 0x8D, 0x77, 0x3F, 0x10, 0x9E, 0xCE,
+ 0xC5, 0x63, 0xA2, 0x67, 0xE3, 0xFE, 0x48, 0xAC,
+ 0x9A, 0x8F, 0x9E, 0xB9, 0x63, 0xB2, 0x2B, 0x59,
+ 0xF1, 0x53, 0x18, 0x95, 0xA8, 0x12, 0x28, 0xAF,
+ 0xCF, 0x97, 0x9A, 0xC9,
+
+ 0x5C, 0x23, 0xC9, 0xB0, 0x2F, 0x8E, 0x8B, 0x75,
+ 0xBC, 0xD3, 0x76, 0x22, 0xD0, 0x83, 0x85, 0x0A,
+ 0xA8, 0xC1, 0xF6, 0x06, 0xD5, 0x80, 0x59, 0xEB,
+ 0xF5, 0xD2, 0xBF, 0x35, 0x76, 0x64, 0xF6, 0x40,
+ 0x2B, 0xC4, 0x59, 0xA4, 0x8A, 0x21, 0x78, 0x77,
+ 0xBD, 0x4C, 0x2D, 0x11, 0x24, 0x31, 0x33, 0xF4,
+ 0x8D, 0x89, 0x61, 0xA4, 0xD9, 0x74, 0xEC, 0xEA,
+ 0xC9, 0x90, 0x9C, 0x79, 0x5D, 0x4B, 0x9E, 0x92,
+ 0xB5, 0x0D, 0x94, 0xE4, 0xCE,
+
+ 0xAC, 0xE3, 0xD3, 0xD0, 0x7C, 0x51, 0x6F, 0xD7,
+ 0x73, 0xC9, 0x82, 0x6B, 0x9A, 0x6C, 0x8D, 0x56,
+ 0xB4, 0x17, 0xB7, 0xD8, 0xAD, 0x80, 0xA7, 0xFC,
+ 0xCA, 0xD5, 0x5B, 0x8E, 0x3A, 0xE3, 0x4B, 0x6B,
+ 0xFD, 0x75, 0x1B, 0xD1, 0xE5, 0xBA, 0x64, 0xD8,
+ 0xC4, 0x29, 0x83, 0xF8, 0x18, 0x98, 0xA2, 0x96,
+ 0x10, 0xB2, 0x3E, 0x60, 0x04, 0xE9, 0x9A, 0x68,
+ 0x2D, 0xFD, 0x41, 0x6A, 0xB7, 0xB4, 0xB8, 0x81,
+ 0x08, 0x54, 0x7A, 0xBF, 0xD1, 0x91,
+
+ 0xA9, 0xB0, 0xF9, 0x25, 0x66, 0xC3, 0xF5, 0x4D,
+ 0x9A, 0x9A, 0x18, 0x15, 0x8E, 0x06, 0x8E, 0xC3,
+ 0x75, 0x7B, 0x99, 0xE2, 0x07, 0x49, 0x41, 0x19,
+ 0xA1, 0x7E, 0x3E, 0x13, 0xED, 0x3E, 0xB9, 0x66,
+ 0x89, 0x37, 0x37, 0xE3, 0xBC, 0xC4, 0xA7, 0xA5,
+ 0xB4, 0x5A, 0x57, 0x1B, 0xF7, 0xAD, 0x54, 0x13,
+ 0xF5, 0x4F, 0x80, 0x3F, 0xF9, 0x02, 0x89, 0xCA,
+ 0xFE, 0x2F, 0xE3, 0xC5, 0x63, 0xB6, 0x4D, 0x72,
+ 0x95, 0x25, 0x51, 0xFE, 0xD7, 0x4C, 0x7B,
+
+ 0xB9, 0x14, 0xD1, 0xAD, 0x98, 0x4B, 0x37, 0x28,
+ 0x4B, 0x73, 0xFE, 0x28, 0x3F, 0x0B, 0x83, 0xC4,
+ 0xB6, 0xED, 0x8D, 0x4E, 0x25, 0x12, 0xB5, 0x41,
+ 0xB3, 0xAC, 0x2C, 0x2A, 0x8B, 0x5C, 0x3D, 0xE6,
+ 0x69, 0xE1, 0x99, 0x18, 0x31, 0x78, 0xCB, 0xAC,
+ 0xA8, 0xE7, 0x7F, 0x44, 0xFF, 0x87, 0xBB, 0x92,
+ 0xBD, 0x98, 0xEF, 0xD3, 0x86, 0x1B, 0xD3, 0xB5,
+ 0xB2, 0x78, 0x56, 0x1D, 0x7A, 0x0C, 0x4D, 0xC7,
+ 0x15, 0xA1, 0x68, 0x10, 0x85, 0x19, 0x39, 0x9A,
+
+ 0x4B, 0x01, 0x86, 0x3D, 0x0D, 0xB2, 0x31, 0x1F,
+ 0xA1, 0xCA, 0x12, 0x0C, 0x59, 0x69, 0xEC, 0x14,
+ 0x62, 0xC9, 0x17, 0xC2, 0x61, 0xF1, 0x60, 0x2B,
+ 0x8C, 0x46, 0x80, 0x62, 0x9E, 0x7E, 0xE4, 0x21,
+ 0xC3, 0x3F, 0xF7, 0x4C, 0x31, 0xCE, 0x8B, 0x4C,
+ 0x87, 0x48, 0xD9, 0x60, 0x39, 0xFD, 0xFC, 0x12,
+ 0x15, 0x2F, 0x35, 0x74, 0x79, 0xEB, 0x87, 0x20,
+ 0x72, 0x23, 0xE6, 0x66, 0x5A, 0xD4, 0xFB, 0x72,
+ 0xA9, 0x6B, 0xDB, 0xB4, 0x30, 0xFD, 0x80, 0xF5,
+ 0xBB,
+
+ 0xBC, 0xD6, 0x2A, 0xC2, 0x2E, 0x81, 0x71, 0xF7,
+ 0xF9, 0x29, 0x5B, 0xBB, 0x8C, 0x84, 0xB3, 0xB2,
+ 0x47, 0xF4, 0xBB, 0x9C, 0x82, 0xC0, 0x35, 0xA2,
+ 0xEA, 0xA7, 0x4E, 0xA5, 0x5E, 0xD5, 0x0D, 0xDF,
+ 0x89, 0x3E, 0xC1, 0x3F, 0x8B, 0x82, 0xE5, 0xEB,
+ 0x4D, 0x87, 0xD9, 0x73, 0xAC, 0x06, 0x8A, 0xB4,
+ 0xF3, 0x2C, 0x83, 0xCB, 0x08, 0xB5, 0xB2, 0x74,
+ 0x16, 0xD0, 0x97, 0x87, 0x53, 0x6C, 0x73, 0x7B,
+ 0x20, 0x0D, 0x18, 0x7F, 0x3A, 0xD6, 0x3D, 0xF0,
+ 0x9E, 0x00,
+
+ 0xE9, 0x20, 0xCF, 0x62, 0x26, 0x4F, 0xA8, 0xA2,
+ 0x8C, 0xCC, 0x32, 0xDE, 0x6B, 0xA5, 0x44, 0xB7,
+ 0xD0, 0x25, 0x48, 0x4B, 0xB7, 0x10, 0x61, 0x3B,
+ 0x93, 0xFB, 0xFB, 0x57, 0x02, 0xBC, 0x02, 0xD2,
+ 0x8E, 0x33, 0x08, 0xBF, 0xA2, 0x02, 0xB4, 0xDF,
+ 0x86, 0x33, 0xCD, 0xCD, 0x7C, 0x3B, 0x8D, 0xDB,
+ 0x90, 0x3A, 0xF3, 0x55, 0x82, 0x73, 0x5F, 0x27,
+ 0x8D, 0xED, 0x06, 0x08, 0x18, 0x27, 0xAF, 0xF8,
+ 0x7B, 0x01, 0x4E, 0xB0, 0xF2, 0xE8, 0xD9, 0x73,
+ 0x43, 0x59, 0xB0,
+
+ 0x92, 0x47, 0x3D, 0x62, 0x6D, 0x82, 0xB4, 0x89,
+ 0x35, 0xCB, 0x4A, 0x66, 0x24, 0xF1, 0x14, 0x40,
+ 0xA6, 0xAD, 0xE1, 0xD4, 0xC8, 0xFB, 0x08, 0x90,
+ 0xFC, 0x33, 0xA8, 0x2E, 0xCF, 0x38, 0x4C, 0x45,
+ 0xF8, 0x8D, 0x4B, 0x11, 0xF8, 0x7F, 0xD8, 0x4F,
+ 0x22, 0x2D, 0x7B, 0x38, 0x8C, 0x8F, 0xDF, 0x8B,
+ 0xF1, 0x4B, 0xCF, 0x46, 0xE5, 0xCC, 0x8D, 0x0A,
+ 0x7A, 0x0E, 0xF8, 0xDE, 0xCE, 0x10, 0xCA, 0xCD,
+ 0xA8, 0x30, 0x0A, 0x63, 0x0E, 0xA0, 0x32, 0x54,
+ 0x5C, 0x77, 0x49, 0xDC,
+
+ 0xED, 0xA1, 0x20, 0xA9, 0x5E, 0x2A, 0xBC, 0xBC,
+ 0x1A, 0x8D, 0x48, 0x71, 0x4E, 0x3A, 0xFA, 0xEA,
+ 0x8F, 0x78, 0x3F, 0xA6, 0x61, 0x28, 0xC3, 0xC9,
+ 0x01, 0xCF, 0xD4, 0x2E, 0x36, 0x40, 0x90, 0xA8,
+ 0xCA, 0x45, 0x40, 0xFE, 0x9E, 0xB6, 0x40, 0x28,
+ 0xFB, 0x28, 0x3E, 0x07, 0xFC, 0xA1, 0x1A, 0x8D,
+ 0xA8, 0x5B, 0xB1, 0x1A, 0xE3, 0x18, 0xDC, 0xB3,
+ 0x19, 0x14, 0xF9, 0xB9, 0x9C, 0xF2, 0x15, 0xE2,
+ 0x70, 0xD5, 0x74, 0xFF, 0x1E, 0xED, 0x92, 0x0C,
+ 0xC9, 0xE7, 0x57, 0x55, 0x8B,
+
+ 0xD5, 0x15, 0x63, 0x0A, 0x41, 0xF9, 0x2B, 0x15,
+ 0x55, 0x1E, 0x63, 0x96, 0xC3, 0xF0, 0x21, 0x90,
+ 0xFB, 0xB9, 0xC7, 0xFE, 0xEE, 0x15, 0x2C, 0x28,
+ 0xBB, 0x2C, 0x9D, 0x6F, 0x8E, 0xAB, 0x73, 0xD3,
+ 0x03, 0x39, 0xE9, 0xB4, 0xEC, 0xED, 0x48, 0x1F,
+ 0xDA, 0x87, 0x29, 0xA1, 0x4B, 0xD7, 0xC8, 0xCD,
+ 0xDB, 0xF0, 0xCF, 0x82, 0x54, 0x27, 0xBF, 0x20,
+ 0xF4, 0xD4, 0x52, 0xED, 0x64, 0xA2, 0x4A, 0x6D,
+ 0xC8, 0x78, 0x1E, 0x83, 0x03, 0xBA, 0x22, 0x9C,
+ 0xFC, 0xB1, 0xE0, 0x67, 0xC7, 0x23,
+
+ 0x62, 0xB2, 0xA4, 0xD4, 0xCD, 0xAE, 0xD3, 0xF1,
+ 0xFB, 0x71, 0x5C, 0xDD, 0xD6, 0x51, 0x91, 0x9D,
+ 0x48, 0xBD, 0x3C, 0xF9, 0x0C, 0x05, 0xEB, 0xF8,
+ 0x55, 0x48, 0x03, 0xE6, 0x9C, 0x13, 0x9E, 0xB8,
+ 0x6B, 0xB5, 0x09, 0xB3, 0x89, 0x04, 0x96, 0xFD,
+ 0x1C, 0xE8, 0x0F, 0xC9, 0x19, 0x85, 0xE4, 0xCC,
+ 0xBB, 0xDB, 0xC3, 0x15, 0x69, 0xD9, 0xA1, 0x91,
+ 0x9B, 0x16, 0xE0, 0xD0, 0x74, 0x3F, 0xF4, 0x2D,
+ 0x33, 0x74, 0x02, 0x1D, 0xE3, 0xDB, 0xF8, 0xD3,
+ 0x33, 0xD9, 0x2F, 0x77, 0x94, 0x6B, 0x20,
+
+ 0x86, 0x99, 0xFC, 0xEF, 0x12, 0x8E, 0x6E, 0x84,
+ 0x7A, 0x25, 0xD3, 0xB6, 0x37, 0xEE, 0x42, 0x0D,
+ 0x88, 0xE2, 0x53, 0xD7, 0x59, 0x4A, 0x73, 0x67,
+ 0xA6, 0x20, 0xA3, 0x91, 0x7C, 0x1F, 0xCA, 0x18,
+ 0xC9, 0xEF, 0xD1, 0xD0, 0xE0, 0xC7, 0x23, 0x14,
+ 0x03, 0x05, 0x7F, 0x84, 0xCD, 0xDB, 0xDB, 0x2D,
+ 0x31, 0x33, 0xBE, 0xD5, 0x1A, 0xDC, 0xC2, 0xBE,
+ 0x6C, 0x9B, 0x35, 0xFB, 0xAD, 0xC1, 0xDE, 0xDC,
+ 0xDC, 0xB9, 0xDE, 0xF5, 0x38, 0xCF, 0x06, 0x95,
+ 0x53, 0x24, 0x47, 0x9F, 0xB8, 0x41, 0x84, 0x9B,
+
+ 0x13, 0x83, 0x54, 0x9F, 0x66, 0xE7, 0x40, 0x2D,
+ 0xD9, 0xB5, 0xB9, 0xAC, 0xB0, 0x08, 0x06, 0x54,
+ 0x50, 0x34, 0x07, 0x8A, 0x2E, 0x0B, 0xF2, 0x06,
+ 0x85, 0xF2, 0x8C, 0xC1, 0x24, 0x2D, 0x9F, 0x66,
+ 0x9A, 0x94, 0x93, 0x0E, 0xFA, 0x5E, 0xCC, 0x1D,
+ 0x74, 0xAE, 0x8F, 0xAA, 0x51, 0x0E, 0x7F, 0xD4,
+ 0x61, 0xA2, 0x29, 0xAB, 0xE9, 0x70, 0x8F, 0x99,
+ 0xFF, 0x11, 0x38, 0x84, 0x63, 0x6D, 0x91, 0xB8,
+ 0xF8, 0x08, 0x01, 0x08, 0x65, 0x39, 0xCF, 0x42,
+ 0x34, 0x29, 0x36, 0xDE, 0x29, 0xE9, 0x44, 0xFE,
+ 0x7E,
+
+ 0x13, 0x26, 0xF8, 0xB2, 0xD9, 0x68, 0xE5, 0x81,
+ 0x20, 0xE6, 0xA3, 0xC8, 0x34, 0x43, 0x4D, 0xCE,
+ 0xA7, 0x87, 0x10, 0x98, 0x35, 0x91, 0x70, 0xF0,
+ 0x1D, 0xA4, 0xFB, 0x73, 0x00, 0x8E, 0x15, 0x49,
+ 0x14, 0xF8, 0xE8, 0x11, 0xA6, 0xBD, 0xEE, 0x7D,
+ 0x51, 0x49, 0x52, 0x5F, 0x0D, 0x63, 0x8D, 0x52,
+ 0x40, 0x4D, 0xF5, 0x40, 0x15, 0x04, 0x7C, 0xE2,
+ 0x23, 0xCE, 0x1F, 0x37, 0x15, 0x2C, 0xDF, 0x92,
+ 0xDC, 0xF7, 0xAB, 0xA5, 0x2B, 0xE8, 0x8C, 0xF9,
+ 0xF1, 0xBC, 0x42, 0x79, 0xE0, 0x6B, 0xBF, 0xEA,
+ 0x74, 0xBA,
+
+ 0xB4, 0x5B, 0x74, 0xCE, 0x30, 0x5A, 0x8C, 0x7B,
+ 0xCE, 0x65, 0x3E, 0x64, 0xEE, 0x0D, 0xC8, 0x91,
+ 0x2E, 0x57, 0x6B, 0xE6, 0xD1, 0x95, 0xCC, 0x64,
+ 0xB6, 0x0E, 0x67, 0xD2, 0xB3, 0x52, 0x78, 0x18,
+ 0x1E, 0xE6, 0x49, 0x32, 0x61, 0x68, 0x94, 0x19,
+ 0x98, 0x54, 0xDB, 0x92, 0x8B, 0x9B, 0x4E, 0x75,
+ 0x93, 0x72, 0x59, 0x63, 0x8D, 0x3F, 0x2F, 0x9C,
+ 0x4D, 0xC6, 0x94, 0x60, 0xDD, 0xD9, 0xB3, 0xB4,
+ 0x04, 0xC0, 0xBC, 0x49, 0x94, 0x01, 0x61, 0x1B,
+ 0xF0, 0xB6, 0x94, 0xCF, 0x21, 0xE6, 0x96, 0x77,
+ 0xDF, 0xB9, 0x13,
+
+ 0xB2, 0xEB, 0xE5, 0x13, 0x22, 0xCD, 0x5F, 0x6C,
+ 0x28, 0xB3, 0xCD, 0x37, 0x6A, 0xCC, 0xC8, 0x59,
+ 0xBC, 0x0A, 0x44, 0xC0, 0x53, 0xB7, 0xD9, 0x1F,
+ 0x6A, 0xD2, 0x7D, 0x34, 0xB8, 0x9F, 0xBF, 0xA7,
+ 0xF2, 0x87, 0x09, 0xF7, 0xE0, 0xDE, 0x43, 0x66,
+ 0xD8, 0xAF, 0x04, 0x03, 0x2A, 0x48, 0xBC, 0x70,
+ 0x49, 0x34, 0x05, 0x03, 0x85, 0xFC, 0x30, 0x78,
+ 0xE5, 0x2A, 0x30, 0x65, 0x95, 0x62, 0xD6, 0x0B,
+ 0x5C, 0xD6, 0x97, 0x4C, 0x65, 0x0A, 0x94, 0xB5,
+ 0x2E, 0xF7, 0x86, 0x30, 0x63, 0x4F, 0xA8, 0x72,
+ 0xAD, 0xF4, 0x19, 0xFB,
+
+ 0x9B, 0x61, 0xE9, 0xE9, 0x8D, 0xB0, 0x02, 0x06,
+ 0x4D, 0x1C, 0x28, 0x5C, 0x65, 0x7E, 0x89, 0x02,
+ 0x47, 0x76, 0x1A, 0x1E, 0xEC, 0x64, 0xBA, 0x8D,
+ 0x59, 0xF0, 0xC5, 0xCE, 0x89, 0xCF, 0x11, 0x5E,
+ 0x3A, 0xBF, 0x8A, 0x32, 0x63, 0xFB, 0xD8, 0xC7,
+ 0x56, 0xA8, 0x6F, 0xF3, 0x2B, 0xC8, 0x5B, 0x8F,
+ 0xEC, 0x2C, 0x91, 0x35, 0x60, 0xE4, 0x84, 0x09,
+ 0x2F, 0x36, 0x8E, 0x4F, 0xFB, 0x06, 0xBD, 0x53,
+ 0xC4, 0x8A, 0x6B, 0x3B, 0xFA, 0x04, 0x50, 0x15,
+ 0x17, 0x63, 0x46, 0x9C, 0x54, 0xF6, 0xB6, 0xA9,
+ 0xEA, 0xE5, 0x60, 0x5E, 0x75,
+
+ 0xC6, 0x4D, 0xA8, 0x7B, 0xC5, 0xC5, 0xDA, 0x2B,
+ 0xBB, 0x19, 0xA2, 0x36, 0xBE, 0x76, 0xA7, 0x34,
+ 0x92, 0xD4, 0xE2, 0xA5, 0xF3, 0xF1, 0xF8, 0xBE,
+ 0xA0, 0xA3, 0xB8, 0xE2, 0x3C, 0x39, 0x34, 0x84,
+ 0xE5, 0xF7, 0x48, 0xF3, 0xD1, 0x4F, 0x4E, 0xC2,
+ 0x4E, 0xB3, 0xC2, 0xBB, 0xE0, 0x1E, 0xAA, 0xBF,
+ 0x42, 0x62, 0x90, 0x4D, 0x62, 0xF5, 0x79, 0xE5,
+ 0x50, 0x25, 0x03, 0x37, 0x90, 0xAA, 0xF7, 0xFC,
+ 0xEB, 0xC0, 0x32, 0xDA, 0x1C, 0xD7, 0x1E, 0xA5,
+ 0x1C, 0x49, 0xF4, 0xE4, 0x94, 0x2D, 0x88, 0xA8,
+ 0x24, 0x7C, 0x0D, 0x1F, 0xB1, 0xA7,
+
+ 0xE5, 0x1F, 0xCF, 0xE1, 0x7A, 0x7C, 0xF5, 0x66,
+ 0x6E, 0x92, 0x41, 0x68, 0x89, 0x5C, 0xD7, 0xB4,
+ 0x24, 0x06, 0xEE, 0x3D, 0x0D, 0xC7, 0xDF, 0xA9,
+ 0x48, 0x39, 0xCB, 0x8E, 0x79, 0xE9, 0xA8, 0x3D,
+ 0xB9, 0xFC, 0x97, 0xF1, 0x03, 0x06, 0xEB, 0xFB,
+ 0x14, 0x97, 0x96, 0xA1, 0xFB, 0x25, 0x12, 0x6D,
+ 0xA9, 0x2B, 0x0C, 0xC1, 0x27, 0x87, 0x4D, 0x17,
+ 0xDE, 0xEA, 0xD3, 0xEE, 0x3A, 0xA9, 0xD5, 0x80,
+ 0x52, 0x0E, 0xBB, 0x15, 0xA8, 0x16, 0x58, 0x25,
+ 0x7A, 0x6C, 0x55, 0x30, 0x80, 0xCE, 0x9B, 0x1E,
+ 0x97, 0x21, 0xD7, 0xEE, 0x5D, 0x4C, 0xE6,
+
+ 0xEE, 0x3C, 0x03, 0x94, 0x28, 0xD8, 0xED, 0x96,
+ 0x2E, 0x67, 0x08, 0xEE, 0xDB, 0x31, 0xD9, 0x42,
+ 0x10, 0x51, 0x99, 0x56, 0x68, 0x60, 0xA6, 0x79,
+ 0x19, 0x7A, 0x54, 0xC3, 0xBD, 0x2A, 0x2D, 0x69,
+ 0xF1, 0xE2, 0xEF, 0xA7, 0x26, 0x3D, 0x9A, 0x6F,
+ 0x26, 0x8D, 0xE3, 0x0E, 0x3B, 0xFB, 0xCC, 0xFF,
+ 0x65, 0x09, 0xAD, 0x24, 0xEE, 0xA8, 0xD8, 0x55,
+ 0x83, 0xF5, 0xEA, 0x61, 0x07, 0x6F, 0x90, 0x54,
+ 0x3C, 0x1A, 0x8E, 0xB0, 0x89, 0x79, 0x8A, 0xA7,
+ 0x35, 0x05, 0x7B, 0xAF, 0xF0, 0xBC, 0x94, 0xB1,
+ 0x59, 0xF2, 0xB8, 0xAA, 0xC9, 0x92, 0x9B, 0x4A,
+
+ 0xF6, 0xF8, 0x0F, 0x47, 0xEF, 0xEB, 0x09, 0xB2,
+ 0xB3, 0xC6, 0x0E, 0xE1, 0xA5, 0xA2, 0x62, 0x6D,
+ 0x44, 0x25, 0xEE, 0xEE, 0x35, 0xD0, 0x18, 0xBE,
+ 0x07, 0xC3, 0xAD, 0x9E, 0x8E, 0x93, 0xBB, 0x78,
+ 0xD7, 0x8F, 0x47, 0x6A, 0x27, 0x4C, 0x39, 0x18,
+ 0xD1, 0xC5, 0xA9, 0x9F, 0x31, 0x7F, 0x47, 0x6A,
+ 0x95, 0x35, 0x74, 0x6B, 0x1C, 0xD5, 0x33, 0x51,
+ 0x68, 0x58, 0x67, 0x89, 0xA8, 0x43, 0x9B, 0xE5,
+ 0xB4, 0x94, 0x5E, 0x62, 0xD5, 0x1C, 0xCB, 0x31,
+ 0x1E, 0x5C, 0xA8, 0x10, 0xA4, 0xC0, 0x62, 0xDE,
+ 0x19, 0xCC, 0x17, 0x09, 0x4A, 0x5B, 0x88, 0xC3,
+ 0xE4,
+
+ 0xFB, 0xD9, 0x1D, 0x95, 0x93, 0x0F, 0xBA, 0xDB,
+ 0x70, 0x42, 0x47, 0x89, 0xB4, 0xF2, 0xCB, 0xF9,
+ 0x65, 0x5F, 0x8D, 0xC7, 0x44, 0x51, 0x39, 0x7F,
+ 0xCC, 0xD2, 0x8A, 0xA7, 0x14, 0xFE, 0xFC, 0x4A,
+ 0x36, 0x50, 0x6E, 0x18, 0xF9, 0xAF, 0x0E, 0xB5,
+ 0xEC, 0x1B, 0xCB, 0x66, 0xE0, 0x1A, 0x41, 0xC2,
+ 0xA8, 0x5F, 0x62, 0x35, 0xE5, 0x9C, 0xCB, 0x35,
+ 0x40, 0x51, 0x54, 0x25, 0xA6, 0xAB, 0x3D, 0x87,
+ 0x13, 0x58, 0x6C, 0x39, 0xEA, 0x09, 0xDE, 0xF4,
+ 0xD9, 0x8D, 0x55, 0xF3, 0xBF, 0x18, 0xDC, 0xD5,
+ 0x9E, 0xD2, 0xCE, 0x9D, 0x38, 0x99, 0x16, 0xB3,
+ 0x67, 0xAB,
+
+ 0xFF, 0x15, 0x86, 0xD2, 0x9C, 0x6E, 0xBB, 0xC6,
+ 0x3F, 0xB4, 0x57, 0x9D, 0x0C, 0x84, 0xCF, 0xE3,
+ 0xAB, 0x55, 0xA6, 0x11, 0x6A, 0xBB, 0xB8, 0x3A,
+ 0x4C, 0x18, 0x53, 0x53, 0x54, 0xAE, 0x1F, 0x48,
+ 0x81, 0x98, 0x10, 0x13, 0x95, 0xE5, 0xF7, 0xC9,
+ 0x7A, 0xE5, 0x08, 0x3D, 0xD2, 0xE3, 0xE0, 0x63,
+ 0x08, 0x2C, 0x53, 0x35, 0x4A, 0xFA, 0xB1, 0x33,
+ 0x8C, 0xE7, 0x4B, 0xE7, 0x56, 0x9C, 0x97, 0x26,
+ 0xC8, 0xD7, 0x8F, 0x37, 0xF0, 0x8C, 0x69, 0x30,
+ 0x6C, 0x6B, 0xE9, 0x50, 0x03, 0xDC, 0xF3, 0x06,
+ 0x02, 0x6B, 0x73, 0x97, 0xF3, 0xC8, 0x51, 0x90,
+ 0x56, 0xEE, 0x6B,
+
+ 0xD1, 0x92, 0x49, 0xBE, 0x13, 0xB9, 0x0D, 0xC3,
+ 0x94, 0x48, 0xF7, 0xAE, 0x8D, 0xB3, 0xCD, 0x40,
+ 0xBB, 0x01, 0x2F, 0x5E, 0x65, 0xBF, 0x15, 0xE7,
+ 0xC9, 0x23, 0xD8, 0x8A, 0x31, 0x92, 0xD4, 0x89,
+ 0x03, 0x92, 0x64, 0x77, 0xC4, 0x02, 0xA1, 0xC8,
+ 0x06, 0xA5, 0x46, 0xD8, 0x83, 0x19, 0x9B, 0x49,
+ 0x2C, 0x77, 0x14, 0x1C, 0x37, 0xEC, 0xBC, 0x16,
+ 0x16, 0x90, 0x38, 0x5D, 0x7B, 0x62, 0xC7, 0x5E,
+ 0xB9, 0x90, 0x4C, 0x86, 0xB1, 0x04, 0x3F, 0x9B,
+ 0x97, 0xFF, 0x96, 0x96, 0xF8, 0x8C, 0xED, 0x30,
+ 0x29, 0x97, 0xCE, 0x39, 0x08, 0xEA, 0xCE, 0xEC,
+ 0xE4, 0xD5, 0x97, 0x80,
+
+ 0xED, 0x40, 0x76, 0x4D, 0x2A, 0x83, 0x9E, 0xB9,
+ 0x0E, 0xA6, 0x9B, 0xFF, 0x43, 0xD3, 0x57, 0x22,
+ 0xA1, 0xE5, 0x19, 0x44, 0x8A, 0x2C, 0x2B, 0xA5,
+ 0xE0, 0x58, 0x00, 0xEA, 0xDE, 0xD7, 0x77, 0x95,
+ 0x98, 0x02, 0x43, 0xC8, 0xAC, 0x9E, 0x10, 0x49,
+ 0xDD, 0xFC, 0x0D, 0x6B, 0x69, 0x0C, 0x5F, 0xA6,
+ 0xBC, 0x11, 0xCB, 0xB0, 0x40, 0x8C, 0xFD, 0xFD,
+ 0x28, 0xEF, 0xEB, 0xAC, 0x73, 0xCD, 0x15, 0x74,
+ 0x49, 0x08, 0x5F, 0xE5, 0xCA, 0x39, 0x3E, 0x07,
+ 0xAB, 0xF0, 0xE8, 0xC3, 0x6F, 0xEC, 0x41, 0x50,
+ 0x29, 0x5A, 0xF8, 0xD8, 0x95, 0x68, 0x77, 0xA9,
+ 0x31, 0x9A, 0x5E, 0xB7, 0xFD,
+
+ 0x4E, 0xB1, 0x03, 0x95, 0xE6, 0x22, 0x49, 0x89,
+ 0xDE, 0x26, 0x73, 0x65, 0x0B, 0xE2, 0x85, 0xA1,
+ 0xC5, 0x15, 0x5B, 0x5F, 0x8D, 0xC8, 0xB3, 0x15,
+ 0xCB, 0x39, 0xD8, 0xD8, 0x12, 0xEF, 0x83, 0x89,
+ 0x02, 0x81, 0x5A, 0x36, 0xB4, 0xAF, 0xE0, 0xA4,
+ 0xE3, 0x1E, 0x72, 0xB6, 0x80, 0x1A, 0xCA, 0xB9,
+ 0xF8, 0x64, 0x80, 0x62, 0x55, 0xA3, 0x50, 0x6F,
+ 0xD0, 0x4C, 0x37, 0xFC, 0xFE, 0x8D, 0xC6, 0xFE,
+ 0xD9, 0x6A, 0x6A, 0x1E, 0x44, 0x35, 0xCF, 0x6A,
+ 0x1F, 0xDC, 0x86, 0x22, 0x74, 0x5D, 0xC9, 0x6A,
+ 0xFA, 0x32, 0x12, 0xB3, 0x12, 0x8A, 0x9D, 0x29,
+ 0x6A, 0xB0, 0x10, 0x73, 0xF3, 0xAF,
+
+ 0xAF, 0x25, 0xCA, 0x2F, 0xCC, 0xAC, 0xEB, 0x64,
+ 0x67, 0xCA, 0x4A, 0xC6, 0xE6, 0x6C, 0x98, 0xC8,
+ 0xB9, 0x12, 0xCF, 0xCD, 0x56, 0xC1, 0x01, 0x32,
+ 0x36, 0xEB, 0xE5, 0x58, 0xAC, 0xEC, 0x2D, 0xA6,
+ 0xF9, 0x95, 0x84, 0xD9, 0x21, 0x13, 0x81, 0xE7,
+ 0x8B, 0x46, 0x34, 0x3E, 0x29, 0xD7, 0x02, 0xAE,
+ 0xC7, 0x45, 0x38, 0xC1, 0x69, 0x70, 0xE9, 0x38,
+ 0x2C, 0x9D, 0x0F, 0xE1, 0x32, 0x48, 0x74, 0x65,
+ 0x8A, 0x20, 0x50, 0x2A, 0x5C, 0xF9, 0x6F, 0xD7,
+ 0xAC, 0x8A, 0xFB, 0x63, 0x24, 0x09, 0x6F, 0x9F,
+ 0xC0, 0x19, 0xA9, 0x84, 0x53, 0x2E, 0x4F, 0x25,
+ 0x22, 0x19, 0x99, 0x6D, 0x63, 0xD6, 0x2F,
+
+ 0x06, 0x07, 0xEB, 0x05, 0xA8, 0x83, 0xC7, 0xFC,
+ 0x5B, 0x09, 0xBF, 0x80, 0xC9, 0x86, 0x1C, 0x98,
+ 0xDD, 0x25, 0xE9, 0xDB, 0x66, 0xC5, 0x49, 0x4F,
+ 0xF0, 0x12, 0xD6, 0x73, 0x04, 0xD7, 0x1B, 0xC6,
+ 0xFF, 0xEB, 0xB7, 0x34, 0x09, 0x74, 0x96, 0xB4,
+ 0xDD, 0xB2, 0x52, 0x3E, 0xB2, 0xDC, 0x9D, 0x4D,
+ 0x12, 0x77, 0x7C, 0x5B, 0xB1, 0x2D, 0x18, 0x35,
+ 0xD0, 0xCF, 0x22, 0x40, 0x2B, 0xEF, 0x91, 0x28,
+ 0xDC, 0x4A, 0xF8, 0xB3, 0xAE, 0x22, 0x7B, 0x9D,
+ 0x1C, 0x92, 0x19, 0xD2, 0x3E, 0x7D, 0xAF, 0xD5,
+ 0x31, 0x95, 0xB0, 0x9A, 0x52, 0xD2, 0xFE, 0x3F,
+ 0x23, 0x37, 0x22, 0xF5, 0xC6, 0xC4, 0x41, 0xCC,
+
+ 0x67, 0x3B, 0x8B, 0xB9, 0x68, 0x4C, 0x7A, 0x96,
+ 0xA1, 0xB1, 0x89, 0x79, 0x49, 0x24, 0xC4, 0x12,
+ 0x42, 0x1A, 0x78, 0x6F, 0xE2, 0x7F, 0xB4, 0x92,
+ 0xCD, 0xC0, 0xAD, 0xF5, 0x2D, 0x87, 0x6D, 0x22,
+ 0x18, 0xFC, 0xCE, 0x69, 0xAA, 0xD8, 0x01, 0x2D,
+ 0x49, 0x64, 0x3C, 0x24, 0xEE, 0xFF, 0xCA, 0x32,
+ 0x34, 0xF5, 0x09, 0x5E, 0x90, 0x50, 0x35, 0xEB,
+ 0xB8, 0x2D, 0x16, 0x10, 0xAD, 0x38, 0x30, 0x3D,
+ 0x97, 0x07, 0xD0, 0x99, 0xCF, 0xF0, 0xA8, 0xBB,
+ 0x21, 0xB0, 0x54, 0xCB, 0x56, 0xC6, 0x72, 0x96,
+ 0x22, 0x58, 0x9A, 0x10, 0xAE, 0xA5, 0xD5, 0x52,
+ 0x0F, 0xB6, 0x3C, 0xF3, 0x16, 0x59, 0x3F, 0x46,
+ 0x56,
+
+ 0xC3, 0xFC, 0x2F, 0xDE, 0xBC, 0xC5, 0xF4, 0xB3,
+ 0x17, 0x21, 0x88, 0xF7, 0xAB, 0x80, 0x06, 0x7A,
+ 0x36, 0x20, 0x97, 0x8A, 0x71, 0x16, 0xB9, 0x38,
+ 0xCF, 0x0E, 0x91, 0xC2, 0x4E, 0x38, 0x99, 0xC8,
+ 0x5B, 0xAA, 0xC0, 0xFC, 0xD4, 0x48, 0x85, 0x3F,
+ 0x41, 0xF0, 0x0A, 0x17, 0x2E, 0x32, 0xD3, 0xD4,
+ 0xF4, 0x43, 0xDE, 0x00, 0x0D, 0xE0, 0xA5, 0x81,
+ 0x2B, 0xB9, 0xF3, 0x9D, 0xE4, 0xA9, 0x29, 0xF1,
+ 0x25, 0x1F, 0x44, 0x7C, 0xBC, 0x84, 0xEA, 0xA1,
+ 0x39, 0xA3, 0x2F, 0x16, 0x7B, 0xEB, 0x47, 0xF6,
+ 0x33, 0x53, 0xD4, 0x4D, 0xFE, 0x63, 0x72, 0x4E,
+ 0x32, 0x72, 0x87, 0x1A, 0xA8, 0x94, 0x56, 0x7B,
+ 0xC0, 0x6E,
+
+ 0xB9, 0x69, 0x4D, 0x32, 0x87, 0xD6, 0xC6, 0x8B,
+ 0xEC, 0xA1, 0xDF, 0xF8, 0x58, 0xB4, 0xCD, 0xCE,
+ 0x1E, 0xC5, 0x37, 0x4E, 0x9B, 0x77, 0x8F, 0x8A,
+ 0xEB, 0x89, 0x03, 0x4A, 0xA0, 0x0F, 0x51, 0x3C,
+ 0x6C, 0x1B, 0x14, 0x7D, 0x0D, 0x1D, 0xBF, 0xA1,
+ 0x8D, 0x59, 0x48, 0xA7, 0x95, 0x24, 0xED, 0x09,
+ 0x8D, 0xDF, 0x89, 0xCA, 0x80, 0xB7, 0x2D, 0x0D,
+ 0x71, 0xC7, 0x73, 0xFA, 0xB0, 0xFE, 0x70, 0xCE,
+ 0xEA, 0xA2, 0x53, 0x23, 0x07, 0x41, 0x5B, 0x75,
+ 0x44, 0x93, 0x0A, 0x36, 0xB3, 0x5A, 0x6C, 0xBD,
+ 0xDA, 0x66, 0x43, 0x55, 0x3C, 0x87, 0xC2, 0x8E,
+ 0x51, 0xA3, 0x28, 0xFB, 0xFB, 0x5F, 0x8E, 0x82,
+ 0xA9, 0x60, 0x5D,
+
+ 0x7E, 0x26, 0x4B, 0x2B, 0x10, 0x93, 0x82, 0xAC,
+ 0x0B, 0x01, 0x88, 0x29, 0x90, 0x43, 0xA7, 0xAE,
+ 0xC5, 0xDE, 0xC6, 0xAB, 0x67, 0x49, 0x45, 0x6B,
+ 0x30, 0x5F, 0x87, 0x59, 0x4D, 0xB2, 0xE0, 0x8B,
+ 0xEC, 0x9F, 0x9D, 0xB6, 0x5E, 0x1A, 0xA8, 0xE8,
+ 0xB2, 0xF5, 0xC4, 0xDB, 0xC1, 0x39, 0xC6, 0xF4,
+ 0x85, 0xE8, 0x59, 0x19, 0xE8, 0xE8, 0xAA, 0xE6,
+ 0xA7, 0xE1, 0x66, 0x1B, 0x9A, 0xE3, 0x7C, 0xCE,
+ 0x5A, 0x7A, 0x3B, 0x32, 0x38, 0x89, 0x60, 0x6B,
+ 0xB8, 0xD9, 0xA1, 0xE2, 0x33, 0x62, 0xDA, 0xED,
+ 0xC0, 0xAF, 0x10, 0x23, 0xCA, 0xD5, 0x18, 0x5F,
+ 0x4F, 0xAC, 0x07, 0x02, 0x5D, 0x62, 0x4B, 0xCF,
+ 0x89, 0x5D, 0xB6, 0x8F,
+
+ 0x4F, 0xB9, 0xC8, 0xBB, 0x61, 0x38, 0x62, 0xC0,
+ 0x7E, 0xDA, 0xBB, 0x97, 0x1F, 0x14, 0x93, 0x3D,
+ 0x56, 0x14, 0x06, 0xA0, 0xDA, 0xA6, 0x2F, 0x8D,
+ 0x61, 0xC6, 0xD3, 0x70, 0x2A, 0xF2, 0xEF, 0xD6,
+ 0x97, 0x81, 0x1B, 0x18, 0xCB, 0x5D, 0x3F, 0xC0,
+ 0xAB, 0xF1, 0xE8, 0x16, 0x59, 0xA3, 0x9E, 0xDC,
+ 0x59, 0x0D, 0x5D, 0x1C, 0x51, 0x81, 0xF6, 0x1A,
+ 0x12, 0x0C, 0xF7, 0xE3, 0xF0, 0x6E, 0x8D, 0x89,
+ 0x8D, 0xED, 0x1F, 0xE7, 0x4E, 0xE9, 0xB0, 0x9A,
+ 0x04, 0xB2, 0x9F, 0xB5, 0x05, 0xBB, 0xE2, 0x70,
+ 0x4F, 0x9F, 0x86, 0x03, 0x86, 0x9C, 0xE9, 0x63,
+ 0x8B, 0xA5, 0x8B, 0xFC, 0xD3, 0xF4, 0x24, 0xE1,
+ 0xE2, 0x46, 0xEB, 0x77, 0x2C,
+
+ 0xD3, 0xE2, 0xB1, 0xBF, 0xE6, 0x28, 0xA2, 0x19,
+ 0x09, 0x7C, 0xE5, 0xDE, 0x6C, 0x07, 0x79, 0x55,
+ 0x36, 0xD2, 0x39, 0x8B, 0x1C, 0x1E, 0xBB, 0x67,
+ 0xF6, 0xE9, 0xA5, 0xD6, 0xCE, 0x83, 0x47, 0xFC,
+ 0x2D, 0x5D, 0xF3, 0x9D, 0xA8, 0x98, 0x78, 0x2B,
+ 0x2A, 0x4B, 0x1C, 0xC8, 0x7F, 0x45, 0x3F, 0x58,
+ 0x01, 0x35, 0xE4, 0x5C, 0xF8, 0xEE, 0x27, 0xC6,
+ 0x53, 0x88, 0x4B, 0x96, 0xDA, 0xBF, 0x57, 0x37,
+ 0x45, 0x2F, 0x4B, 0xDC, 0x57, 0x74, 0xD9, 0x69,
+ 0x15, 0x94, 0x60, 0x45, 0x72, 0xFA, 0x52, 0x05,
+ 0x2B, 0xA5, 0xF2, 0x85, 0x6F, 0x3C, 0xF6, 0xF1,
+ 0xF8, 0x4A, 0xAF, 0xF4, 0xC3, 0x0D, 0x6A, 0x8C,
+ 0xF3, 0xBC, 0x6A, 0x07, 0x02, 0x15,
+
+ 0xBE, 0x63, 0x59, 0xA9, 0x6D, 0x8D, 0x63, 0xB4,
+ 0x80, 0xB1, 0xEA, 0xCD, 0x8B, 0xB3, 0x98, 0x8A,
+ 0x63, 0xF3, 0x0C, 0xD6, 0x93, 0xC0, 0x9E, 0x88,
+ 0x33, 0x19, 0x0F, 0xC0, 0xF0, 0xFE, 0xCC, 0x33,
+ 0xC7, 0xC5, 0xF0, 0xD6, 0x73, 0x6D, 0x57, 0xA4,
+ 0x4C, 0x49, 0x20, 0x10, 0x99, 0x68, 0x73, 0x99,
+ 0x38, 0xE9, 0x25, 0x11, 0x8B, 0xE1, 0xC8, 0x90,
+ 0x13, 0x6A, 0x96, 0x0F, 0x82, 0x23, 0xFD, 0x5E,
+ 0x71, 0x8D, 0x6E, 0xA4, 0x37, 0x7C, 0x35, 0xC6,
+ 0x37, 0xD3, 0xC8, 0xBE, 0x4B, 0x59, 0x94, 0xE2,
+ 0x5C, 0x70, 0xEB, 0x62, 0xC5, 0xF1, 0x7E, 0x63,
+ 0x02, 0xCE, 0xE4, 0x07, 0x38, 0x2E, 0x8F, 0x63,
+ 0x8D, 0xAC, 0xBB, 0x93, 0xAB, 0x8D, 0x71,
+
+ 0x52, 0xBD, 0xA1, 0x06, 0x3C, 0x94, 0x40, 0x14,
+ 0x24, 0x66, 0x94, 0x84, 0x7F, 0x92, 0x07, 0x8C,
+ 0x02, 0xB4, 0x9A, 0x9D, 0x77, 0x91, 0xDC, 0xEC,
+ 0x69, 0xC6, 0x9F, 0xD5, 0x89, 0xDE, 0x3A, 0x55,
+ 0xF1, 0x8C, 0x2D, 0xAD, 0xBE, 0x56, 0x1B, 0x88,
+ 0x4D, 0xE1, 0x88, 0x8A, 0xEF, 0xFB, 0x2B, 0x1A,
+ 0xE0, 0xEF, 0xF3, 0x79, 0xED, 0x25, 0x23, 0xF3,
+ 0xAA, 0x1B, 0xE1, 0xF6, 0xB3, 0x0E, 0xC4, 0xA7,
+ 0x02, 0xBB, 0xCC, 0x25, 0x08, 0x67, 0x75, 0x23,
+ 0xE6, 0x0D, 0x5E, 0x4E, 0xE9, 0x00, 0xB3, 0xA8,
+ 0x7F, 0xB3, 0x42, 0x08, 0x7B, 0x36, 0xC8, 0x4A,
+ 0x67, 0xCA, 0xC3, 0x8E, 0xEC, 0x62, 0xB3, 0xA1,
+ 0x2E, 0x8A, 0xB6, 0x60, 0xE0, 0xD6, 0x38, 0xA9,
+
+ 0x9E, 0x06, 0x4A, 0xB5, 0x71, 0xD7, 0x33, 0x84,
+ 0x95, 0x9C, 0x5F, 0xF8, 0x12, 0x0D, 0x46, 0xFA,
+ 0xE5, 0x67, 0x31, 0xE2, 0x71, 0xDC, 0xB6, 0xB4,
+ 0xE1, 0x3B, 0x16, 0x28, 0xE5, 0x04, 0x20, 0x90,
+ 0xC1, 0x70, 0xB3, 0x1C, 0x93, 0xF6, 0x6E, 0xC8,
+ 0x42, 0x8A, 0xAC, 0x85, 0x67, 0xB5, 0xAE, 0x74,
+ 0x78, 0xFA, 0x32, 0x4B, 0x0D, 0x74, 0x3B, 0x38,
+ 0xF9, 0x31, 0x01, 0xDA, 0x65, 0xE1, 0xBA, 0x5B,
+ 0x47, 0xE5, 0xCE, 0x58, 0xC6, 0x16, 0x6D, 0xC2,
+ 0x56, 0xB7, 0x9B, 0x43, 0x0B, 0x81, 0x65, 0xDD,
+ 0xF5, 0xB9, 0x44, 0x93, 0x06, 0xD6, 0x07, 0x8B,
+ 0xDF, 0xE7, 0x1F, 0x14, 0xD6, 0x04, 0x4F, 0xFD,
+ 0x47, 0x67, 0xEB, 0xBF, 0x23, 0xEB, 0xA7, 0xEE,
+ 0xB0,
+
+ 0x31, 0xCF, 0x75, 0x5F, 0xFF, 0xBD, 0xB1, 0xE7,
+ 0x04, 0xBF, 0x32, 0x3F, 0x80, 0x8C, 0x1A, 0xCF,
+ 0x78, 0xF2, 0x95, 0x2B, 0x4B, 0xEF, 0x30, 0xDF,
+ 0xE4, 0x49, 0x04, 0xF3, 0x82, 0x11, 0x30, 0x6B,
+ 0x30, 0x3C, 0xAA, 0x9B, 0x1F, 0xDB, 0xFA, 0xDA,
+ 0xC3, 0x79, 0x88, 0x1F, 0x4C, 0x06, 0x7E, 0xE5,
+ 0x89, 0x04, 0x78, 0x7C, 0x0B, 0xA0, 0x2D, 0x50,
+ 0x88, 0xD4, 0xA8, 0x3C, 0x4D, 0x9F, 0x85, 0x9E,
+ 0x6A, 0x0C, 0xC6, 0x75, 0xE5, 0x02, 0x19, 0x64,
+ 0xA6, 0x64, 0x21, 0x76, 0x2F, 0x2E, 0xBC, 0xDA,
+ 0xF0, 0xDD, 0x19, 0xCE, 0xB1, 0xB6, 0x35, 0x3F,
+ 0x6B, 0x3F, 0xCF, 0xFD, 0x71, 0x2E, 0x0C, 0x4B,
+ 0x8B, 0x4D, 0x26, 0xDA, 0x06, 0x46, 0xE3, 0x68,
+ 0xBA, 0x22,
+
+ 0xA3, 0x90, 0x81, 0xE3, 0xBA, 0x9C, 0x12, 0x57,
+ 0xE3, 0x53, 0x6E, 0x90, 0x2F, 0xD4, 0x6B, 0x23,
+ 0x58, 0xCD, 0x1C, 0xBD, 0x6F, 0x8B, 0x16, 0x0C,
+ 0x40, 0x41, 0x47, 0x86, 0xA4, 0xA2, 0x90, 0x6C,
+ 0x81, 0x8B, 0x51, 0x53, 0xC8, 0x9A, 0xF4, 0x4F,
+ 0x04, 0xB0, 0xF3, 0xE2, 0xDE, 0x73, 0x17, 0x3B,
+ 0xB3, 0xDB, 0x61, 0xFB, 0xBD, 0xC8, 0xBB, 0x13,
+ 0x8A, 0xE9, 0xB0, 0x5D, 0x38, 0x5F, 0x3F, 0x7A,
+ 0xDC, 0xB2, 0x25, 0xB7, 0x0B, 0xBD, 0xC6, 0xD6,
+ 0x8F, 0x15, 0xD5, 0x17, 0x2E, 0x84, 0xD0, 0xA6,
+ 0xA8, 0x72, 0xEA, 0x2D, 0x2C, 0xE9, 0x31, 0x8D,
+ 0x22, 0x6B, 0x0F, 0xD8, 0x36, 0x70, 0x3C, 0x11,
+ 0xBE, 0x32, 0x2D, 0xB1, 0x14, 0xCD, 0x90, 0x18,
+ 0x99, 0xCA, 0x01,
+
+ 0xA9, 0x3C, 0xC6, 0x55, 0x5C, 0xA3, 0x2C, 0x02,
+ 0x51, 0xB8, 0x98, 0xF0, 0xDE, 0xF3, 0x51, 0x7A,
+ 0x1F, 0x6C, 0xA1, 0xCD, 0x15, 0xCB, 0x3B, 0x3A,
+ 0x7E, 0xD5, 0x3E, 0xF0, 0xD5, 0xE4, 0x6F, 0x30,
+ 0x3C, 0x1F, 0x92, 0x65, 0xEE, 0x40, 0xAC, 0x8F,
+ 0x8A, 0xA5, 0x5D, 0x26, 0x38, 0xCE, 0x02, 0xDE,
+ 0xA4, 0xF6, 0xC1, 0xB5, 0x53, 0x7B, 0x37, 0x40,
+ 0x38, 0xC6, 0x31, 0x9B, 0x3F, 0x72, 0x0D, 0x91,
+ 0x46, 0xD9, 0xE3, 0x17, 0xAD, 0x07, 0x1D, 0xDE,
+ 0x69, 0xF9, 0xBD, 0x72, 0x1E, 0x4E, 0x68, 0x4E,
+ 0x16, 0x48, 0xAD, 0xEA, 0x9C, 0x18, 0x70, 0xDF,
+ 0x7E, 0x38, 0x4F, 0x68, 0xC5, 0xE2, 0xA1, 0x09,
+ 0x5E, 0x5F, 0x42, 0x75, 0x66, 0x20, 0xE6, 0xE3,
+ 0x1F, 0xAC, 0x76, 0x6D,
+
+ 0xCE, 0x61, 0xD7, 0xE9, 0x85, 0xCF, 0xEF, 0xDC,
+ 0x2D, 0x75, 0x04, 0x60, 0x76, 0xF1, 0x4E, 0xE9,
+ 0x72, 0xD3, 0x2E, 0x6A, 0x5A, 0x81, 0xB0, 0xAF,
+ 0x29, 0x05, 0xAF, 0x9C, 0xEF, 0xF1, 0xF3, 0x96,
+ 0x97, 0x10, 0xCA, 0x15, 0xA9, 0x73, 0x44, 0xFC,
+ 0x61, 0x0D, 0x2E, 0xE5, 0x1A, 0x3B, 0x24, 0x5E,
+ 0x04, 0xAE, 0x5B, 0xCA, 0x40, 0xEC, 0x4B, 0x92,
+ 0xD8, 0x7C, 0x3F, 0x0B, 0x69, 0x9B, 0x3C, 0xC4,
+ 0x9E, 0x80, 0x3C, 0x2B, 0xB1, 0x39, 0xFB, 0xC6,
+ 0x8A, 0x65, 0x98, 0x1A, 0x53, 0xE1, 0x31, 0x90,
+ 0xE6, 0x26, 0x43, 0x73, 0x07, 0xAD, 0x80, 0xD9,
+ 0x4C, 0xC0, 0x0E, 0x5F, 0xE7, 0x6D, 0x0B, 0xEB,
+ 0xD1, 0x16, 0x0A, 0x57, 0xFB, 0x49, 0xF5, 0xA0,
+ 0x96, 0x6E, 0x9A, 0xB0, 0x82,
+
+ 0xC7, 0x84, 0x16, 0x76, 0x54, 0xAE, 0x96, 0x80,
+ 0x66, 0x9E, 0xCF, 0xB2, 0x49, 0x57, 0x8B, 0x32,
+ 0xDA, 0x1C, 0xCD, 0xD1, 0xA7, 0x44, 0x52, 0x19,
+ 0x5A, 0x77, 0x8D, 0x9D, 0x89, 0xC4, 0x84, 0xD0,
+ 0x2D, 0xFB, 0x8D, 0xB5, 0xCD, 0x63, 0x48, 0x6E,
+ 0x18, 0x49, 0x1B, 0xFA, 0x48, 0xD5, 0x32, 0xBB,
+ 0x85, 0x0A, 0x90, 0xBC, 0x6C, 0xAF, 0x5D, 0x6F,
+ 0xAC, 0x34, 0xF9, 0xC6, 0x59, 0x85, 0xE8, 0xC2,
+ 0xA2, 0xA4, 0x9F, 0x77, 0xE4, 0x00, 0xEE, 0x94,
+ 0xD9, 0x57, 0xEC, 0x31, 0x7E, 0x0F, 0xB1, 0xD2,
+ 0xD5, 0xA5, 0x1A, 0xBE, 0x0C, 0xC2, 0x85, 0x7B,
+ 0x5E, 0xCD, 0xD0, 0xB6, 0x1E, 0x04, 0x86, 0xEF,
+ 0x84, 0x74, 0x6B, 0x97, 0x5D, 0x6B, 0x5C, 0x63,
+ 0x81, 0x50, 0x6F, 0x4F, 0x8E, 0x1B,
+
+ 0xC7, 0x9C, 0x57, 0x9D, 0xE5, 0x46, 0x4F, 0xC1,
+ 0x4A, 0x03, 0x63, 0x2E, 0x35, 0x1B, 0x35, 0x9D,
+ 0xD3, 0xA7, 0xB5, 0xDC, 0xCD, 0x58, 0xEB, 0x25,
+ 0x52, 0x9E, 0xC0, 0xB3, 0x19, 0x85, 0x11, 0x65,
+ 0x14, 0x8A, 0x27, 0x0F, 0xDD, 0xB5, 0x06, 0xCE,
+ 0x9A, 0x1A, 0xD8, 0xB5, 0x07, 0x63, 0x24, 0x5F,
+ 0xD2, 0xBC, 0x79, 0xB8, 0x62, 0x45, 0x10, 0xBC,
+ 0x65, 0x00, 0x22, 0x94, 0x83, 0x60, 0x62, 0xF3,
+ 0x13, 0xE1, 0xD0, 0x5D, 0x47, 0xD8, 0xCB, 0x2C,
+ 0x59, 0x60, 0x9D, 0x8F, 0x9A, 0x49, 0x7F, 0x60,
+ 0x71, 0x85, 0xA5, 0x53, 0xCE, 0x55, 0x72, 0x30,
+ 0x89, 0xD6, 0x74, 0x5B, 0xEE, 0xAF, 0x48, 0x60,
+ 0x1C, 0x0A, 0xD0, 0x56, 0x54, 0xC5, 0x40, 0x1B,
+ 0x1F, 0x94, 0xAE, 0x5E, 0x45, 0x60, 0x59,
+
+ 0xD1, 0x73, 0xAA, 0xD6, 0x76, 0x3F, 0x35, 0xDE,
+ 0x77, 0x82, 0x96, 0xFF, 0x1B, 0x34, 0xAD, 0x16,
+ 0x77, 0x73, 0xD7, 0x8A, 0x96, 0x19, 0xA0, 0xBA,
+ 0x22, 0x71, 0x36, 0x9D, 0xAC, 0x41, 0x14, 0xAB,
+ 0xA8, 0x77, 0x34, 0x7A, 0x70, 0x2A, 0xF6, 0xF6,
+ 0xEA, 0xFD, 0x6D, 0xDB, 0xAD, 0x65, 0x14, 0x3A,
+ 0xEA, 0x0E, 0x2C, 0xC4, 0xC1, 0x13, 0x7D, 0x59,
+ 0x8D, 0xE8, 0x61, 0x29, 0x50, 0x61, 0xC3, 0xC9,
+ 0x76, 0x20, 0x7C, 0xEF, 0x09, 0xA8, 0xC3, 0x8E,
+ 0x11, 0xD2, 0x3F, 0x32, 0x09, 0x61, 0x91, 0xF8,
+ 0x60, 0xF6, 0x83, 0x93, 0x08, 0x94, 0xBF, 0x5D,
+ 0x6E, 0xDE, 0xA1, 0x04, 0xEE, 0xB2, 0xE3, 0x10,
+ 0x1D, 0x22, 0xF0, 0xF8, 0x4E, 0x5C, 0xF5, 0x9B,
+ 0x86, 0x44, 0x57, 0x28, 0xB7, 0x8C, 0x81, 0x14,
+
+ 0x31, 0xDF, 0xA5, 0xD5, 0xF6, 0x17, 0x19, 0x50,
+ 0xA3, 0x0F, 0x26, 0x1C, 0xD4, 0x98, 0xCA, 0xB0,
+ 0xDB, 0x0C, 0x2F, 0x8C, 0xCE, 0xCC, 0x56, 0x35,
+ 0x57, 0xC2, 0x9D, 0xEF, 0x64, 0x82, 0xE4, 0x8A,
+ 0xFA, 0xFE, 0x07, 0xF1, 0xB7, 0x10, 0xDF, 0x56,
+ 0x7B, 0x64, 0x88, 0x9C, 0x25, 0xF1, 0x6D, 0x6C,
+ 0x5F, 0xD3, 0xC8, 0xC4, 0x7E, 0xD5, 0x26, 0xB8,
+ 0xC3, 0xDD, 0xAD, 0x85, 0x3E, 0xA0, 0x5C, 0x33,
+ 0x25, 0x9A, 0xD9, 0x52, 0xB7, 0x8C, 0x22, 0x3F,
+ 0x96, 0xD4, 0x51, 0x7C, 0x9F, 0xAD, 0x01, 0x81,
+ 0xBE, 0x95, 0x90, 0x38, 0x90, 0xDD, 0x81, 0x43,
+ 0xB0, 0x66, 0x0D, 0x4E, 0x9E, 0xF6, 0x0C, 0x13,
+ 0x47, 0xA5, 0xA0, 0x1F, 0x94, 0xFB, 0x86, 0x42,
+ 0x8B, 0x9B, 0x22, 0x25, 0xF2, 0xB8, 0x83, 0x3C,
+ 0x87,
+
+ 0x06, 0xFA, 0x95, 0x25, 0x62, 0x35, 0x4D, 0x06,
+ 0x3F, 0xD2, 0xAE, 0x4E, 0x86, 0x32, 0x08, 0x54,
+ 0x78, 0x35, 0xAD, 0x84, 0xE1, 0x6D, 0xB1, 0x5E,
+ 0xD0, 0x91, 0x42, 0x02, 0x39, 0x1F, 0x0D, 0x4C,
+ 0xE5, 0x4B, 0xDB, 0x9D, 0x1A, 0xE5, 0x05, 0x97,
+ 0x90, 0x0F, 0xB4, 0xCD, 0xC5, 0xF7, 0xDA, 0x81,
+ 0xC7, 0x22, 0x25, 0xB8, 0xAA, 0xC5, 0xA6, 0x6C,
+ 0xCD, 0x21, 0xC3, 0xCA, 0xFA, 0xDB, 0x0C, 0xDC,
+ 0x35, 0x7B, 0x49, 0x2E, 0xC9, 0xD4, 0xDC, 0x2C,
+ 0xF5, 0x2A, 0x3E, 0xBA, 0x93, 0x52, 0x88, 0x73,
+ 0x4B, 0x3A, 0x1E, 0x5B, 0x37, 0xE4, 0x54, 0x8E,
+ 0xE7, 0x3C, 0x78, 0x37, 0xBA, 0x31, 0x09, 0x3A,
+ 0xE0, 0x36, 0xFF, 0x6C, 0x7D, 0xA9, 0x68, 0x0F,
+ 0x33, 0xCD, 0x1B, 0x7E, 0xD0, 0x12, 0x98, 0xC7,
+ 0xC6, 0x9E,
+
+ 0x59, 0xBC, 0xD3, 0x93, 0xD5, 0x73, 0x5C, 0x4F,
+ 0xCD, 0x32, 0x8C, 0xA7, 0xEC, 0xB1, 0x92, 0x82,
+ 0xFF, 0x08, 0x94, 0xED, 0xCE, 0x65, 0x7E, 0xDD,
+ 0x28, 0x65, 0xEA, 0xDB, 0x3B, 0x77, 0x87, 0x41,
+ 0x5A, 0xE7, 0xE4, 0x4F, 0x5D, 0xC6, 0x8E, 0xB7,
+ 0xD5, 0x83, 0x5A, 0xA4, 0x1B, 0xE5, 0x40, 0x50,
+ 0xA1, 0x0E, 0xB3, 0x8F, 0xE3, 0x31, 0x87, 0xD8,
+ 0xBF, 0xD9, 0xBE, 0x07, 0x68, 0x9F, 0xAF, 0xD5,
+ 0x5A, 0xB3, 0xEB, 0x4B, 0x59, 0x0E, 0xDA, 0x36,
+ 0xE8, 0xCE, 0x29, 0x5A, 0x9D, 0x68, 0xF7, 0x40,
+ 0xAD, 0xD4, 0x4C, 0xEC, 0xD3, 0xB1, 0xF8, 0x13,
+ 0x5B, 0x4B, 0x9A, 0xE9, 0x7A, 0x19, 0x37, 0x21,
+ 0x35, 0x2F, 0x01, 0xE3, 0xF0, 0x7E, 0xF4, 0x80,
+ 0x3E, 0xBF, 0xB0, 0xDB, 0xB8, 0x5B, 0x46, 0xBF,
+ 0x81, 0xB2, 0x6D,
+
+ 0xE6, 0x27, 0x7B, 0xD7, 0x3A, 0x57, 0x4A, 0x57,
+ 0x1F, 0x16, 0x60, 0x67, 0xE3, 0xCB, 0x95, 0x54,
+ 0x52, 0x0F, 0xD3, 0xF8, 0x2E, 0x4E, 0xFE, 0xAC,
+ 0x98, 0x99, 0x14, 0x6E, 0x24, 0x91, 0x5A, 0x2C,
+ 0xA1, 0xDE, 0x40, 0xBB, 0x2E, 0x59, 0x23, 0x98,
+ 0xCE, 0x15, 0x9A, 0xDC, 0x0D, 0x1B, 0xB2, 0xC4,
+ 0x6C, 0xC3, 0x23, 0xBE, 0xCB, 0xF3, 0xF6, 0x67,
+ 0xCF, 0x10, 0x5B, 0x90, 0xEE, 0xAC, 0x62, 0x54,
+ 0xCA, 0x9C, 0xD4, 0xD4, 0x83, 0x41, 0x1B, 0x46,
+ 0xD8, 0x42, 0x0B, 0x01, 0x7B, 0xC2, 0x1B, 0xD0,
+ 0x6A, 0x55, 0x1D, 0x2F, 0x2D, 0xF3, 0x63, 0xCD,
+ 0xAC, 0xCB, 0x30, 0xF0, 0x95, 0x7C, 0x9E, 0x37,
+ 0xA8, 0x37, 0x42, 0xA5, 0xAC, 0xCC, 0xA2, 0xFD,
+ 0x6E, 0x90, 0x0B, 0x64, 0x50, 0x38, 0x72, 0x7A,
+ 0x0B, 0x7E, 0x50, 0xFF,
+
+ 0xAF, 0xB6, 0xBB, 0x4A, 0x9E, 0x62, 0xFB, 0xD7,
+ 0xDA, 0x69, 0xA1, 0x60, 0x20, 0x32, 0xE6, 0x56,
+ 0xA1, 0x6F, 0x37, 0xCA, 0x2D, 0x23, 0xBC, 0x39,
+ 0xED, 0xEF, 0xB7, 0xEE, 0x47, 0x4E, 0xCB, 0x46,
+ 0xD3, 0xCA, 0x19, 0xF6, 0x58, 0x4C, 0x31, 0x2B,
+ 0x65, 0xD6, 0xBC, 0x74, 0x21, 0x05, 0xD7, 0x99,
+ 0x96, 0x8F, 0x47, 0xE4, 0xD8, 0x4B, 0xD1, 0x60,
+ 0x27, 0x2E, 0x9B, 0xBF, 0x22, 0xC4, 0xAC, 0x37,
+ 0xDB, 0x41, 0x61, 0xF6, 0xA7, 0x25, 0x4B, 0xC6,
+ 0x75, 0x97, 0x0B, 0x17, 0xCB, 0x49, 0x60, 0x5A,
+ 0x3E, 0xB6, 0xD7, 0x88, 0x8D, 0x02, 0x89, 0xB3,
+ 0xB0, 0xCC, 0x03, 0xE4, 0x6F, 0x87, 0x44, 0xFF,
+ 0x01, 0x6D, 0xC0, 0xC9, 0xC5, 0x78, 0x34, 0xD2,
+ 0x33, 0x91, 0x0D, 0x51, 0x7A, 0xD9, 0x4D, 0x68,
+ 0x91, 0x47, 0xAB, 0xF9, 0xA1,
+
+ 0x7B, 0x15, 0x4A, 0xEF, 0x0F, 0xD6, 0x75, 0xB7,
+ 0x1B, 0x32, 0x8B, 0x31, 0xC1, 0xCD, 0x3A, 0xF8,
+ 0x7F, 0x2F, 0xA5, 0xBD, 0x7C, 0x5C, 0x43, 0x82,
+ 0x4A, 0x01, 0x3B, 0x50, 0x59, 0x74, 0xB5, 0x61,
+ 0x40, 0x3B, 0xC0, 0xF3, 0xA1, 0x3E, 0x75, 0x36,
+ 0x85, 0x74, 0xC3, 0xB3, 0x55, 0xB6, 0xAB, 0xFC,
+ 0xE9, 0x36, 0x9E, 0x01, 0x1E, 0xCB, 0xEA, 0x1B,
+ 0xB2, 0x02, 0xD8, 0x42, 0x75, 0xD7, 0x36, 0x5E,
+ 0x45, 0x17, 0x0E, 0xDF, 0x33, 0xEF, 0x97, 0xCE,
+ 0xC5, 0x1D, 0x41, 0x4A, 0x06, 0xD3, 0xA1, 0x2F,
+ 0x5C, 0xD6, 0x7F, 0xE1, 0x45, 0xF7, 0x69, 0xC5,
+ 0xFA, 0xE6, 0x88, 0x3A, 0xCB, 0x96, 0xC0, 0xA4,
+ 0xB7, 0x50, 0x9C, 0x67, 0xA2, 0x12, 0x85, 0xC3,
+ 0x0D, 0xD3, 0x0A, 0xE2, 0x58, 0xD7, 0x94, 0x42,
+ 0xFD, 0x3D, 0x54, 0xA7, 0x08, 0x85,
+
+ 0x56, 0x28, 0xAF, 0x54, 0xEA, 0x3E, 0xF7, 0xCF,
+ 0xB9, 0x44, 0xE1, 0xB6, 0x1D, 0x0D, 0xE5, 0x3F,
+ 0xDF, 0x47, 0x9D, 0xE4, 0x94, 0xA0, 0xBF, 0x0E,
+ 0xE1, 0xC1, 0x13, 0x73, 0x0F, 0x23, 0xB1, 0xBE,
+ 0xC1, 0x19, 0xD5, 0x4E, 0x0D, 0x19, 0xA0, 0xD5,
+ 0x20, 0xDD, 0xEA, 0xA9, 0x05, 0x27, 0xF7, 0x8C,
+ 0x3C, 0xB3, 0x18, 0x07, 0xDC, 0x11, 0xE8, 0x60,
+ 0xC2, 0x61, 0x67, 0xAD, 0x0B, 0x6C, 0xA9, 0xD9,
+ 0x3D, 0x65, 0xE9, 0x31, 0x68, 0xFB, 0x3F, 0xDF,
+ 0x4B, 0x0C, 0x3B, 0xC6, 0x51, 0xE4, 0x77, 0x73,
+ 0x9D, 0xB5, 0x5C, 0x37, 0x3B, 0xDD, 0xAD, 0xF2,
+ 0xA8, 0x22, 0x98, 0x4D, 0x5F, 0x4B, 0xE6, 0xE1,
+ 0x0A, 0x46, 0x60, 0x0F, 0xDE, 0x02, 0xF9, 0xE6,
+ 0xFC, 0x3E, 0x22, 0x5D, 0x42, 0x66, 0x50, 0x60,
+ 0x67, 0x8C, 0x16, 0x28, 0xC4, 0x87, 0x02,
+
+ 0x7E, 0xF5, 0xA3, 0x08, 0x91, 0x76, 0x3F, 0x65,
+ 0x90, 0xBF, 0xA2, 0xD7, 0x38, 0x6B, 0x41, 0x4E,
+ 0xC7, 0xD5, 0xBE, 0xEC, 0x60, 0xC5, 0x80, 0x3B,
+ 0xD6, 0x7A, 0x45, 0x4A, 0x44, 0x0F, 0xA1, 0x28,
+ 0xB5, 0x5C, 0x58, 0xB4, 0x2F, 0x56, 0xD3, 0xB9,
+ 0x43, 0x49, 0x09, 0x5E, 0xA6, 0x50, 0xFE, 0xCF,
+ 0x6A, 0x1D, 0x26, 0xC5, 0x4E, 0x96, 0x1A, 0xD0,
+ 0xBA, 0x3F, 0x8D, 0x8D, 0xB1, 0x9E, 0x13, 0x66,
+ 0xCB, 0x9C, 0xEC, 0x57, 0x34, 0x59, 0x7C, 0x8F,
+ 0xE7, 0xE4, 0x8A, 0x52, 0x77, 0x31, 0x0A, 0x7C,
+ 0xB2, 0xD4, 0x80, 0x89, 0xCA, 0x09, 0xAD, 0x93,
+ 0xBC, 0x96, 0x60, 0xBE, 0xB7, 0x92, 0xD5, 0xDA,
+ 0xBB, 0x2C, 0x3B, 0xF6, 0x80, 0xA1, 0xFA, 0xB7,
+ 0x06, 0xA9, 0x5D, 0x74, 0x16, 0x5F, 0x4D, 0xBD,
+ 0xDF, 0x2B, 0x45, 0xA4, 0x14, 0xBA, 0x65, 0xBF,
+
+ 0xDB, 0xE7, 0xA9, 0x45, 0xFF, 0x17, 0xA2, 0xCE,
+ 0xC3, 0x98, 0x34, 0xD0, 0x2F, 0xC2, 0xC1, 0xAE,
+ 0x0A, 0xC0, 0x0B, 0xFF, 0x6A, 0x0D, 0xA1, 0xAB,
+ 0xDA, 0x0B, 0x58, 0xA0, 0x85, 0xFC, 0xF1, 0xC7,
+ 0x53, 0x09, 0x22, 0x4E, 0xBC, 0x0D, 0x32, 0x83,
+ 0x2D, 0xF9, 0x06, 0x38, 0x18, 0x55, 0xC3, 0x6D,
+ 0x79, 0x46, 0x9D, 0x10, 0x5F, 0x14, 0xFB, 0x02,
+ 0x1D, 0xAD, 0x3A, 0xB2, 0x16, 0x48, 0xB5, 0xAD,
+ 0xB7, 0x24, 0x59, 0x93, 0x09, 0xA3, 0xDE, 0x52,
+ 0xE4, 0x4E, 0x63, 0xB8, 0xF4, 0x2E, 0x04, 0x90,
+ 0x10, 0x70, 0xE6, 0x2D, 0xE9, 0x27, 0xEC, 0x20,
+ 0x28, 0xF9, 0xBB, 0xF0, 0x1B, 0xF6, 0xB1, 0xA9,
+ 0x74, 0x60, 0x93, 0xF9, 0x39, 0x5D, 0x45, 0x29,
+ 0x43, 0x7B, 0x06, 0x50, 0x4B, 0x81, 0x79, 0xC1,
+ 0xF4, 0xBB, 0x71, 0x60, 0xE6, 0x1F, 0x93, 0xB2,
+ 0x33,
+
+ 0xA8, 0xE6, 0xE9, 0xEB, 0x5A, 0xE1, 0xDE, 0x41,
+ 0xE9, 0x3E, 0x93, 0x29, 0xA3, 0x8C, 0x26, 0x4C,
+ 0x89, 0x01, 0x48, 0x46, 0x39, 0xB7, 0x49, 0x8D,
+ 0xAD, 0xDB, 0x76, 0x22, 0x74, 0x1C, 0x49, 0x79,
+ 0x61, 0x36, 0x56, 0x16, 0x10, 0x20, 0x68, 0x5E,
+ 0xBF, 0x1A, 0x25, 0x87, 0x7F, 0xC6, 0xB8, 0x17,
+ 0xB6, 0x4F, 0x89, 0xDD, 0x6A, 0x72, 0xD8, 0xF7,
+ 0xDF, 0x27, 0x50, 0xBF, 0x93, 0x26, 0xFE, 0x7A,
+ 0xD3, 0x55, 0x54, 0xC7, 0x23, 0x18, 0xFC, 0x88,
+ 0x47, 0x1A, 0x58, 0x51, 0x49, 0xE7, 0xC0, 0xAB,
+ 0xF8, 0xC8, 0x54, 0x38, 0xE0, 0x75, 0x6B, 0x47,
+ 0x1D, 0x5F, 0xC2, 0x60, 0x59, 0x72, 0x92, 0x57,
+ 0x5C, 0x2E, 0x0D, 0xAC, 0x94, 0x9A, 0x86, 0x74,
+ 0xF0, 0x42, 0x98, 0x11, 0x41, 0xE8, 0x3A, 0x3F,
+ 0xBA, 0xE4, 0xB4, 0xB6, 0x0E, 0x85, 0x11, 0xBC,
+ 0xB3, 0x23,
+
+ 0x3C, 0xD8, 0x11, 0xEC, 0xC7, 0xBB, 0xA6, 0x7C,
+ 0x7F, 0x06, 0x4F, 0x7E, 0xBF, 0x3F, 0xA1, 0x96,
+ 0x65, 0x75, 0xC4, 0xDC, 0x2C, 0x2D, 0x89, 0x6D,
+ 0x75, 0xCB, 0xDD, 0xB2, 0xF9, 0x4F, 0x1B, 0x4C,
+ 0xE7, 0xCA, 0x02, 0xA5, 0x64, 0x6A, 0xEE, 0xEF,
+ 0x0B, 0xDF, 0xE8, 0x79, 0x2C, 0xBA, 0x0F, 0x46,
+ 0x17, 0xA0, 0x45, 0x14, 0x0C, 0x99, 0x2E, 0x66,
+ 0x09, 0xFC, 0x17, 0xD5, 0x03, 0xA3, 0x50, 0x98,
+ 0x82, 0xD6, 0x1B, 0x53, 0xBE, 0x27, 0x4D, 0xB3,
+ 0xBD, 0xC0, 0x43, 0x81, 0x75, 0x7D, 0xCF, 0x11,
+ 0xC7, 0x70, 0x50, 0x01, 0x0C, 0x08, 0x2E, 0xE3,
+ 0x81, 0xC7, 0x04, 0x43, 0xDE, 0x6F, 0x59, 0xB7,
+ 0x9E, 0x82, 0x33, 0x74, 0x6D, 0xF9, 0x0A, 0xE5,
+ 0x69, 0x99, 0xFC, 0x54, 0x73, 0xD8, 0xC8, 0x5A,
+ 0x65, 0x43, 0x45, 0xE0, 0x1B, 0xF4, 0xFA, 0x80,
+ 0xA0, 0x86, 0x7F,
+
+ 0xB3, 0x36, 0xBC, 0x71, 0x8B, 0x9A, 0x93, 0x81,
+ 0x95, 0xD8, 0x5E, 0xF8, 0xDA, 0x56, 0x9E, 0xDB,
+ 0xF2, 0xBE, 0xFE, 0xB0, 0x57, 0xA6, 0x85, 0x48,
+ 0x59, 0x72, 0xEF, 0xB4, 0xF2, 0xFD, 0x5E, 0x98,
+ 0x9C, 0x74, 0x84, 0x52, 0xED, 0x88, 0xFA, 0x97,
+ 0x5C, 0x91, 0x4E, 0x34, 0x92, 0xD3, 0xC4, 0x4C,
+ 0x1B, 0x2F, 0x5F, 0xC8, 0x9B, 0xF1, 0xF6, 0x60,
+ 0x8F, 0xA5, 0x3E, 0xEC, 0x15, 0x2F, 0xCA, 0xC6,
+ 0xFF, 0xB9, 0xDD, 0x3E, 0x05, 0x6F, 0xAE, 0xE2,
+ 0x67, 0xD7, 0xF5, 0xE6, 0x93, 0x74, 0x07, 0x54,
+ 0x86, 0x62, 0xA3, 0x14, 0x4B, 0x8F, 0x00, 0xEA,
+ 0x70, 0x29, 0x15, 0xA5, 0x05, 0x9A, 0xFE, 0xFE,
+ 0xF5, 0x74, 0xE7, 0x29, 0xA1, 0x2C, 0x37, 0xEF,
+ 0x08, 0x81, 0xE0, 0x63, 0x4C, 0x0B, 0x4C, 0xD8,
+ 0xAF, 0x3A, 0x13, 0x11, 0x16, 0x03, 0x5C, 0x73,
+ 0x74, 0x6D, 0xDB, 0xD2,
+
+ 0x84, 0x6D, 0xEF, 0xF2, 0x61, 0x96, 0xD3, 0x49,
+ 0x3A, 0x6E, 0x30, 0x46, 0xB9, 0x56, 0x8A, 0x81,
+ 0xC0, 0xCB, 0xDF, 0x5B, 0xCD, 0x5A, 0xAE, 0xF1,
+ 0xA1, 0x10, 0xE7, 0x03, 0x9A, 0xAE, 0x61, 0x16,
+ 0x2F, 0xD0, 0x0C, 0x26, 0x7A, 0x96, 0x8E, 0x3A,
+ 0x97, 0x8A, 0x0A, 0xC9, 0x90, 0x7F, 0x1E, 0x98,
+ 0xF2, 0x17, 0x74, 0xE7, 0xD1, 0xB2, 0x7F, 0x0F,
+ 0xE6, 0x19, 0x80, 0x2F, 0x83, 0x22, 0x63, 0xDD,
+ 0x73, 0x01, 0xEB, 0xC7, 0x72, 0xC7, 0x87, 0xBA,
+ 0x76, 0xF2, 0x53, 0xD2, 0xDD, 0x23, 0x91, 0x4F,
+ 0x67, 0x6F, 0x69, 0x74, 0xB4, 0xD8, 0x24, 0x20,
+ 0xD8, 0x29, 0x91, 0x78, 0xD6, 0xA2, 0xE0, 0x42,
+ 0x4C, 0xAE, 0x3A, 0xFB, 0xAB, 0x01, 0x70, 0xCF,
+ 0x57, 0xE7, 0xD0, 0x17, 0xF0, 0x4E, 0x9D, 0x52,
+ 0x4C, 0x37, 0x25, 0xA3, 0x23, 0x16, 0x82, 0x89,
+ 0x40, 0x64, 0xA4, 0x0C, 0x5A,
+
+ 0x69, 0xB0, 0x3E, 0x4F, 0x95, 0x66, 0xFD, 0x32,
+ 0x6D, 0x68, 0xF4, 0xDD, 0x78, 0x1D, 0x54, 0x43,
+ 0xD1, 0xB2, 0x50, 0x71, 0x1C, 0x48, 0xDB, 0x8E,
+ 0xE0, 0x58, 0x1A, 0x89, 0xE0, 0x37, 0x64, 0x76,
+ 0x69, 0x85, 0xB9, 0x34, 0x82, 0xA5, 0x57, 0xAE,
+ 0x2A, 0x03, 0x00, 0x9B, 0x97, 0xCF, 0xE1, 0x59,
+ 0x94, 0x74, 0x07, 0x63, 0xD9, 0x6B, 0xBC, 0x1B,
+ 0x03, 0xD9, 0xE4, 0x40, 0xA5, 0xCB, 0x63, 0xF4,
+ 0xA1, 0xBA, 0x2F, 0xCE, 0x1A, 0x8F, 0xB7, 0x5A,
+ 0xB9, 0xFE, 0xEF, 0x8C, 0xA6, 0x74, 0x97, 0xC0,
+ 0xD6, 0x80, 0xB7, 0x2F, 0x03, 0xD8, 0x9B, 0x6E,
+ 0x36, 0x5D, 0xCC, 0x92, 0x21, 0x6E, 0xB8, 0x02,
+ 0xFA, 0xF9, 0xEA, 0x24, 0xA0, 0x3F, 0xDA, 0x2A,
+ 0xD9, 0x43, 0x1C, 0x07, 0xF2, 0x0A, 0x2C, 0x75,
+ 0x3D, 0x42, 0xDB, 0xEA, 0x33, 0xAB, 0x9D, 0x95,
+ 0xBE, 0x53, 0xF6, 0xAC, 0x56, 0xEB,
+
+ 0x80, 0x25, 0xA8, 0x28, 0x34, 0x43, 0x8F, 0xDB,
+ 0xE4, 0xB8, 0x7A, 0x84, 0xE3, 0x12, 0x2E, 0xD3,
+ 0x28, 0x14, 0xFE, 0x42, 0x90, 0x95, 0x26, 0x2B,
+ 0xA1, 0x19, 0x69, 0x23, 0xCF, 0x9D, 0x91, 0xF4,
+ 0xD4, 0xF3, 0x3A, 0xCF, 0xA0, 0x61, 0x3E, 0x91,
+ 0xBF, 0xEE, 0x5B, 0xF8, 0x4E, 0xBE, 0xA0, 0x0A,
+ 0xAB, 0xBC, 0xE4, 0x6A, 0x11, 0x45, 0x20, 0xEA,
+ 0x3B, 0x29, 0xB7, 0xCA, 0x79, 0x75, 0x06, 0x48,
+ 0x4B, 0x7E, 0x11, 0xC5, 0xA8, 0x6A, 0x51, 0x9B,
+ 0x32, 0xBA, 0x3A, 0xA4, 0x06, 0x69, 0xC6, 0xD7,
+ 0x8F, 0xDE, 0x67, 0x52, 0x63, 0xFC, 0x71, 0x99,
+ 0x62, 0x10, 0x4B, 0x58, 0x77, 0xAB, 0x16, 0xBC,
+ 0x5D, 0xDF, 0x25, 0x45, 0xB3, 0x37, 0x03, 0x12,
+ 0x42, 0xAE, 0x77, 0xBD, 0xD5, 0x59, 0x37, 0x62,
+ 0x28, 0x8C, 0x0F, 0x70, 0x3B, 0x0B, 0x08, 0x2B,
+ 0x13, 0xAE, 0x21, 0x58, 0x20, 0x38, 0xDC,
+
+ 0xCE, 0xFA, 0x4C, 0xBD, 0xCA, 0xBC, 0x3A, 0xC0,
+ 0x4B, 0x91, 0x3F, 0x33, 0x19, 0x46, 0x05, 0x16,
+ 0x80, 0xC0, 0xE2, 0x63, 0xB0, 0xE0, 0xD5, 0x2B,
+ 0xCE, 0xBA, 0x01, 0x36, 0x5B, 0xCD, 0x68, 0x17,
+ 0xCF, 0xEC, 0x0A, 0x31, 0x45, 0x36, 0x1B, 0x28,
+ 0xB1, 0x85, 0x90, 0x55, 0xB5, 0x27, 0x90, 0xE1,
+ 0x09, 0x4E, 0x8E, 0x27, 0x91, 0xD7, 0x15, 0x70,
+ 0x85, 0x89, 0x20, 0x0D, 0xD3, 0xF1, 0x70, 0x74,
+ 0xAA, 0x29, 0x0A, 0xA2, 0xA3, 0x96, 0x4B, 0x6E,
+ 0xBB, 0x04, 0x99, 0x4D, 0xC9, 0xD8, 0xFB, 0xA3,
+ 0xD0, 0xEF, 0x9D, 0x2A, 0x77, 0xC9, 0x0E, 0x85,
+ 0x33, 0x68, 0xFC, 0x30, 0xA1, 0x48, 0x55, 0x75,
+ 0x55, 0x21, 0xC8, 0x1F, 0x01, 0xF2, 0xA5, 0x2B,
+ 0x7D, 0xD7, 0x5E, 0x8C, 0x76, 0x06, 0x18, 0xBD,
+ 0x74, 0x4A, 0x5F, 0xE4, 0xE9, 0xD7, 0xCB, 0xEB,
+ 0x37, 0x95, 0x4F, 0x06, 0x26, 0xD2, 0xF1, 0xD4,
+
+ 0x37, 0x0D, 0xA6, 0xE9, 0x34, 0x06, 0x17, 0x74,
+ 0x20, 0x52, 0x8E, 0x5B, 0xC2, 0x71, 0x8D, 0x6E,
+ 0x3C, 0xAA, 0xAA, 0xF9, 0x7F, 0x82, 0x09, 0x74,
+ 0x29, 0xCF, 0x79, 0xC1, 0xF7, 0x42, 0xB8, 0xA9,
+ 0x36, 0xA5, 0xFF, 0x77, 0x15, 0x09, 0x0B, 0x04,
+ 0x7E, 0xF4, 0xE1, 0xB1, 0x88, 0x89, 0x7A, 0x88,
+ 0x98, 0xD3, 0xA7, 0x95, 0x23, 0x69, 0x88, 0xD3,
+ 0x8F, 0x61, 0x1E, 0xBF, 0x99, 0xAD, 0xB4, 0x56,
+ 0xDF, 0x37, 0x12, 0x78, 0xDA, 0xF7, 0xDA, 0x42,
+ 0x8A, 0x43, 0xBD, 0x1A, 0xB2, 0x0A, 0xDA, 0x71,
+ 0xD6, 0x16, 0xDB, 0x15, 0xCA, 0xEA, 0x74, 0xA2,
+ 0x11, 0x0D, 0xAE, 0xE5, 0x2B, 0x64, 0x01, 0x61,
+ 0x91, 0x38, 0x16, 0xF4, 0x6E, 0xB9, 0x01, 0xDF,
+ 0xFD, 0xCD, 0x56, 0x79, 0xA7, 0x42, 0x7D, 0x8C,
+ 0xF4, 0x10, 0x4B, 0x00, 0xBA, 0x05, 0x77, 0x35,
+ 0x29, 0x74, 0x45, 0xDF, 0xCF, 0x2A, 0x6E, 0xBF,
+ 0x60,
+
+ 0x49, 0x06, 0x7D, 0xD6, 0xE2, 0xC8, 0x54, 0x45,
+ 0x41, 0x97, 0x98, 0x29, 0xB5, 0x49, 0x3C, 0xE2,
+ 0x29, 0xC1, 0x87, 0xAC, 0x4A, 0x88, 0x31, 0x54,
+ 0x12, 0xDF, 0x6F, 0x7C, 0x88, 0xD4, 0x5A, 0x69,
+ 0xEF, 0x89, 0xB7, 0x26, 0xBD, 0x5D, 0x14, 0x45,
+ 0x5B, 0xAA, 0xC0, 0x31, 0x77, 0x20, 0x56, 0x22,
+ 0x32, 0x43, 0x0B, 0x0F, 0x29, 0x9F, 0x2C, 0xA5,
+ 0x42, 0xFC, 0x25, 0x1C, 0x9C, 0x1B, 0xE7, 0xBE,
+ 0x65, 0x8F, 0xBD, 0xA8, 0x07, 0xCC, 0x54, 0xFF,
+ 0xD2, 0x3B, 0xC0, 0x52, 0x9F, 0x21, 0xDE, 0xA4,
+ 0xA0, 0x8F, 0xB9, 0x05, 0x51, 0x8B, 0x4D, 0x6C,
+ 0x87, 0x4A, 0xD3, 0x82, 0xD4, 0x0D, 0xE2, 0x11,
+ 0xAC, 0x48, 0x81, 0x6D, 0xF9, 0xFD, 0xEC, 0x8D,
+ 0x15, 0x38, 0x8E, 0x6B, 0xE4, 0x5B, 0x04, 0x42,
+ 0xD5, 0x34, 0xFB, 0xE1, 0xBC, 0x0D, 0xDB, 0xB7,
+ 0xA9, 0xF7, 0xE6, 0x42, 0x5C, 0xBF, 0x89, 0x57,
+ 0x63, 0xF6,
+
+ 0x90, 0x0A, 0xF6, 0x05, 0x11, 0x92, 0x82, 0x59,
+ 0xA1, 0x31, 0x54, 0xE8, 0x93, 0x6C, 0xE5, 0x4B,
+ 0xE8, 0x6C, 0x14, 0x80, 0xFB, 0x5F, 0xB5, 0x52,
+ 0xAA, 0x4A, 0x04, 0x64, 0xC5, 0xC5, 0x03, 0x2C,
+ 0x2D, 0xB1, 0x6F, 0xDC, 0xA0, 0x74, 0xFF, 0xDE,
+ 0xE5, 0x0D, 0x50, 0xE0, 0xBE, 0x35, 0xBA, 0x42,
+ 0x5E, 0x56, 0x64, 0x4F, 0xA0, 0x19, 0xD0, 0xAC,
+ 0xC6, 0x79, 0x09, 0x61, 0x1C, 0x72, 0xE2, 0x38,
+ 0x66, 0x7E, 0x96, 0x61, 0xC7, 0x69, 0x41, 0xEF,
+ 0x5A, 0x41, 0x89, 0xB2, 0xC6, 0xA9, 0xF3, 0xCB,
+ 0x8C, 0xAE, 0x1E, 0xBE, 0xDE, 0xF2, 0x4B, 0x20,
+ 0x67, 0xFF, 0x89, 0xAD, 0x95, 0x0A, 0x4D, 0x2C,
+ 0xEC, 0x62, 0x45, 0x53, 0x5C, 0xD8, 0x8F, 0x41,
+ 0x1B, 0x5E, 0xC6, 0x8E, 0xF6, 0x79, 0xB1, 0x3E,
+ 0xD5, 0x95, 0x46, 0x4E, 0x85, 0xA2, 0x32, 0x79,
+ 0x06, 0xE5, 0xBE, 0xD0, 0xEB, 0x77, 0xE0, 0x87,
+ 0x87, 0x75, 0xDD,
+
+ 0xAC, 0x14, 0x1B, 0x69, 0xEE, 0x01, 0x0E, 0xE8,
+ 0x55, 0x78, 0x58, 0x91, 0xBE, 0xB4, 0x31, 0xCD,
+ 0x3D, 0xBE, 0x2F, 0x30, 0x81, 0x9D, 0x5F, 0x3A,
+ 0x65, 0x49, 0x1E, 0x24, 0x75, 0x38, 0xEA, 0x0F,
+ 0x45, 0x88, 0x6F, 0x66, 0x98, 0x56, 0x84, 0x41,
+ 0xB0, 0x7B, 0x08, 0x92, 0xE1, 0xAC, 0x8E, 0xFD,
+ 0x51, 0x96, 0xAD, 0x8B, 0x2D, 0x8C, 0xB8, 0xFA,
+ 0xB8, 0xA6, 0x63, 0x34, 0xF3, 0xC1, 0xCB, 0x51,
+ 0xC2, 0xAB, 0x04, 0x9B, 0x53, 0x28, 0xF9, 0x13,
+ 0xF0, 0x11, 0x54, 0xFF, 0xB0, 0x47, 0x18, 0x29,
+ 0xC5, 0x97, 0x43, 0x5E, 0x7C, 0xAA, 0x6F, 0x38,
+ 0x99, 0x04, 0x5C, 0x79, 0xF0, 0x08, 0xA2, 0x69,
+ 0xD3, 0xFF, 0x62, 0xC6, 0xDB, 0xA8, 0x2B, 0xF5,
+ 0xDB, 0xD2, 0x8A, 0xDD, 0x4F, 0xC3, 0xD2, 0x00,
+ 0xE5, 0xDE, 0x75, 0xD7, 0xC4, 0x8B, 0x76, 0xC8,
+ 0xDB, 0x55, 0xCB, 0xE6, 0x1B, 0xAB, 0xD2, 0x4E,
+ 0x3B, 0x93, 0x08, 0x43,
+
+ 0x10, 0x07, 0x49, 0x6C, 0x11, 0x44, 0xEE, 0xFA,
+ 0x41, 0x19, 0xFA, 0xD1, 0x7D, 0xEC, 0xD2, 0x8F,
+ 0xA2, 0xBC, 0xB5, 0x38, 0x85, 0xD5, 0x4B, 0x79,
+ 0xFB, 0x77, 0x69, 0x42, 0x65, 0xEC, 0x29, 0x04,
+ 0x24, 0xCF, 0x51, 0xE1, 0xC2, 0x23, 0x06, 0x88,
+ 0x47, 0xAE, 0x7D, 0xA1, 0x08, 0x9A, 0x82, 0x2C,
+ 0xD6, 0xB4, 0x4D, 0x84, 0x96, 0x19, 0x17, 0x5A,
+ 0x0F, 0x22, 0x29, 0xDE, 0x0F, 0x8F, 0x71, 0xAE,
+ 0x12, 0x65, 0x87, 0xC5, 0xB4, 0xAD, 0x58, 0xDB,
+ 0xCA, 0x66, 0xE6, 0xB8, 0xE4, 0x3A, 0x80, 0x2B,
+ 0x18, 0x88, 0xD6, 0x21, 0xDC, 0x2B, 0xC8, 0x52,
+ 0x4B, 0x48, 0x90, 0x37, 0x72, 0x02, 0xCD, 0x01,
+ 0xEC, 0xE8, 0x03, 0xD4, 0x28, 0x8D, 0xD1, 0x94,
+ 0xBC, 0x1E, 0xAE, 0xA2, 0x79, 0x12, 0xB0, 0x5D,
+ 0x34, 0x32, 0x53, 0x1B, 0xC9, 0xA8, 0x6A, 0x1D,
+ 0x48, 0x30, 0x08, 0xB4, 0xC5, 0x54, 0x0A, 0x1E,
+ 0x24, 0x9E, 0x8D, 0x58, 0xF2,
+
+ 0x1C, 0x73, 0x21, 0xCA, 0xB9, 0x20, 0x75, 0xEF,
+ 0xF4, 0x2B, 0xA5, 0xE5, 0x66, 0x62, 0xF3, 0x31,
+ 0x61, 0x92, 0x8B, 0x34, 0x44, 0x67, 0xC5, 0xAD,
+ 0xC1, 0x56, 0xC3, 0xB7, 0x23, 0xC6, 0x2B, 0xB1,
+ 0x34, 0x5F, 0xEF, 0xF7, 0x70, 0x21, 0x5E, 0x35,
+ 0x36, 0x28, 0xCC, 0xD2, 0x61, 0x58, 0xA3, 0xF6,
+ 0xB0, 0xD7, 0xA2, 0xBC, 0xF3, 0x02, 0x4E, 0x76,
+ 0x55, 0x1D, 0x48, 0x45, 0x90, 0x4C, 0xEF, 0x6C,
+ 0xAC, 0x58, 0x7B, 0xF2, 0x7C, 0x3E, 0x3F, 0xD6,
+ 0xFB, 0x57, 0x74, 0x3B, 0x91, 0xBE, 0xCE, 0x05,
+ 0x58, 0x9E, 0x26, 0xE6, 0x8A, 0x96, 0x8B, 0x00,
+ 0xC3, 0x28, 0x4A, 0xE8, 0x5C, 0xDA, 0x46, 0xF2,
+ 0x55, 0x14, 0x7C, 0x86, 0x58, 0xE0, 0x78, 0x16,
+ 0x0B, 0xA6, 0x45, 0xB2, 0xBD, 0x09, 0x83, 0x16,
+ 0xFE, 0x8F, 0x0D, 0xE6, 0x46, 0xE4, 0x85, 0x80,
+ 0x95, 0xE5, 0xC7, 0xEC, 0x5A, 0xE2, 0xE8, 0x1F,
+ 0xCC, 0x33, 0x25, 0x2A, 0x71, 0xB4,
+
+ 0xDF, 0x62, 0x81, 0xFF, 0x5B, 0x88, 0x34, 0xB3,
+ 0xA9, 0x4A, 0xA6, 0xD9, 0x08, 0x48, 0x65, 0x7D,
+ 0xFC, 0x07, 0x56, 0xD8, 0xF5, 0xBA, 0x69, 0xD2,
+ 0xF8, 0x68, 0xAD, 0xDB, 0x14, 0x6F, 0x3F, 0x27,
+ 0x0B, 0x1D, 0x14, 0x53, 0x2C, 0xC2, 0x9E, 0x7E,
+ 0x1A, 0x97, 0xA2, 0xE3, 0x0B, 0x9E, 0x78, 0x3C,
+ 0x79, 0x4B, 0xD9, 0xCC, 0xDD, 0x19, 0x0D, 0x26,
+ 0x77, 0x65, 0xE6, 0x89, 0x19, 0xAB, 0x58, 0xA3,
+ 0x91, 0x50, 0x82, 0xA0, 0xB1, 0xB3, 0x7E, 0xD7,
+ 0x4B, 0xE2, 0xA2, 0xF7, 0x1E, 0x37, 0x33, 0x18,
+ 0xF6, 0x09, 0x60, 0x6B, 0x00, 0x46, 0xEF, 0xB1,
+ 0x06, 0x60, 0x1B, 0x0A, 0x4C, 0x0E, 0xE3, 0xFA,
+ 0xEA, 0xD7, 0x9D, 0xDC, 0x6B, 0x4C, 0x9E, 0x9C,
+ 0x61, 0x22, 0xAB, 0x19, 0x6E, 0x62, 0xA7, 0x25,
+ 0x26, 0xC3, 0xDB, 0x9B, 0xE0, 0x6E, 0xD4, 0x2D,
+ 0xDC, 0x71, 0x2A, 0x13, 0x7C, 0x77, 0xE8, 0xAA,
+ 0x1D, 0xED, 0x37, 0xB5, 0x6A, 0xB8, 0x3E,
+
+ 0x02, 0xDC, 0x62, 0xA2, 0x98, 0x84, 0x22, 0x1E,
+ 0xB7, 0x25, 0x9A, 0xED, 0xDD, 0x60, 0x96, 0x44,
+ 0xEB, 0x1B, 0xC6, 0x9A, 0xEE, 0x76, 0x1B, 0x67,
+ 0xF4, 0x66, 0xE8, 0x63, 0x55, 0x3F, 0x6F, 0xB9,
+ 0x35, 0xAE, 0xB4, 0x3D, 0xD4, 0xDC, 0x4B, 0xD9,
+ 0x42, 0x1F, 0x7A, 0x36, 0x4D, 0x2C, 0x01, 0x2A,
+ 0x74, 0x5B, 0x67, 0xF9, 0xE1, 0x66, 0x69, 0xEF,
+ 0x89, 0x17, 0x96, 0xFF, 0x3F, 0xC6, 0x6C, 0xAB,
+ 0xFA, 0xE8, 0x82, 0x6D, 0x65, 0x48, 0xD2, 0x8D,
+ 0x0D, 0xCB, 0x0F, 0x5B, 0x2E, 0xCF, 0x17, 0xEA,
+ 0x60, 0x96, 0x76, 0x64, 0x33, 0x9A, 0xDE, 0x11,
+ 0xB4, 0x2A, 0xC4, 0x2D, 0x35, 0x2B, 0xF8, 0x36,
+ 0x80, 0xC4, 0x4E, 0xFE, 0x14, 0xFD, 0xB2, 0x57,
+ 0x0A, 0x46, 0x29, 0x37, 0x50, 0x7B, 0x26, 0x29,
+ 0x2B, 0xAE, 0x3D, 0xB9, 0xF8, 0x38, 0x31, 0x4C,
+ 0x13, 0x67, 0xD5, 0xF2, 0x40, 0x92, 0x09, 0xF1,
+ 0x5C, 0xE1, 0xF3, 0xE7, 0xE3, 0x6B, 0x25, 0x88,
+
+ 0x70, 0x64, 0x4F, 0x22, 0x92, 0xCC, 0xBA, 0x70,
+ 0x10, 0xB5, 0xF9, 0x5D, 0xF6, 0xBD, 0x95, 0x7A,
+ 0x9E, 0xA1, 0xC3, 0x00, 0x77, 0x6A, 0x12, 0x94,
+ 0x43, 0xC9, 0x0C, 0xBB, 0xE2, 0xCD, 0xBE, 0xB7,
+ 0xF4, 0x11, 0xB0, 0x86, 0x11, 0xBB, 0x98, 0x31,
+ 0xBE, 0xC0, 0x82, 0xF9, 0x84, 0xF7, 0x99, 0xA6,
+ 0x1A, 0x44, 0x66, 0x28, 0x93, 0x32, 0xD9, 0x91,
+ 0x16, 0x8F, 0x53, 0x0D, 0x21, 0xF4, 0xFC, 0x69,
+ 0x5F, 0xDD, 0xFE, 0xF5, 0x59, 0x9A, 0x96, 0x4F,
+ 0x1C, 0x2A, 0xFD, 0xE4, 0x88, 0x66, 0x2A, 0x78,
+ 0x33, 0x60, 0xF3, 0x10, 0x55, 0xED, 0x68, 0xE6,
+ 0x34, 0x67, 0x62, 0x04, 0xBF, 0x39, 0x17, 0x3D,
+ 0x1B, 0x22, 0x8A, 0x77, 0x45, 0x90, 0x7C, 0x5C,
+ 0xCF, 0x4E, 0xE2, 0xB0, 0x88, 0xB8, 0x2B, 0x4A,
+ 0x4F, 0xCC, 0x14, 0xDC, 0xD3, 0x6A, 0x77, 0xA7,
+ 0xA7, 0x52, 0x0A, 0x4A, 0xCC, 0x3C, 0x30, 0xF0,
+ 0x9B, 0x10, 0x1A, 0xAA, 0xC8, 0x5A, 0xFE, 0x6F,
+ 0xA6,
+
+ 0xC1, 0x62, 0xCF, 0x2C, 0xBA, 0xC0, 0xC0, 0x84,
+ 0x67, 0x4E, 0x96, 0xA2, 0xFF, 0x81, 0xE6, 0x74,
+ 0xFA, 0x22, 0xCE, 0x6B, 0xC4, 0x9C, 0x1D, 0x03,
+ 0xC0, 0xB1, 0x8B, 0x10, 0x33, 0xC3, 0x1F, 0x61,
+ 0x2D, 0x67, 0x09, 0x2F, 0x04, 0x51, 0x49, 0xCE,
+ 0x9F, 0x94, 0x14, 0xAB, 0x0A, 0x7F, 0x39, 0xD9,
+ 0xA5, 0x4F, 0x4E, 0x5A, 0x3C, 0xCB, 0xB8, 0x74,
+ 0x51, 0x28, 0x3B, 0xBE, 0x1B, 0x5E, 0x94, 0xFC,
+ 0xD1, 0xB2, 0x0A, 0x46, 0x20, 0xB3, 0x7E, 0x6E,
+ 0xD3, 0x9F, 0x76, 0x3F, 0x4A, 0xFF, 0x0B, 0xB7,
+ 0x52, 0xE2, 0xA4, 0xDF, 0x2E, 0x0C, 0x72, 0xE2,
+ 0xC7, 0x91, 0x2D, 0x5F, 0xB3, 0x38, 0x4F, 0x03,
+ 0x5C, 0x19, 0x2F, 0xBD, 0xDC, 0x84, 0xB5, 0xF9,
+ 0xFF, 0x8C, 0x19, 0x6F, 0x57, 0x4A, 0xD7, 0xA6,
+ 0xC5, 0x93, 0x2E, 0xEA, 0x35, 0xD7, 0xF8, 0xD4,
+ 0x08, 0xCA, 0x21, 0x06, 0x21, 0x12, 0x9B, 0xE2,
+ 0xF5, 0x38, 0x2C, 0xD4, 0x02, 0xD9, 0x56, 0xDE,
+ 0x5D, 0xB5,
+
+ 0x1F, 0x86, 0xAE, 0xE4, 0xE4, 0xB2, 0x42, 0x60,
+ 0x9B, 0xBF, 0x1E, 0xA5, 0x16, 0x65, 0xA0, 0xDD,
+ 0xB3, 0xC6, 0xCA, 0xD7, 0xB8, 0xAE, 0x14, 0xCD,
+ 0xDF, 0xE9, 0xFF, 0x63, 0x38, 0x87, 0xE8, 0x2F,
+ 0xAE, 0xC7, 0xC7, 0x43, 0x46, 0x24, 0x54, 0xC0,
+ 0x41, 0xA6, 0x27, 0x73, 0x4E, 0x63, 0x0D, 0x0F,
+ 0x2D, 0xAA, 0xD6, 0x62, 0xFE, 0x8E, 0xE4, 0x3F,
+ 0xA2, 0xC3, 0x98, 0x5B, 0x93, 0x5B, 0x11, 0xEA,
+ 0xC9, 0x6D, 0xED, 0x9E, 0x71, 0x9D, 0xD9, 0x5E,
+ 0xA7, 0xB3, 0x4C, 0xB9, 0xBF, 0x2C, 0xE0, 0x90,
+ 0x3C, 0x19, 0x82, 0xE5, 0x94, 0xB9, 0xD7, 0x67,
+ 0x3F, 0xA7, 0x78, 0xAE, 0x10, 0x8B, 0x59, 0x69,
+ 0xD3, 0x73, 0x33, 0x2C, 0xD5, 0x74, 0x76, 0x56,
+ 0xA5, 0x16, 0xF0, 0x78, 0xB9, 0x4E, 0xFA, 0x0B,
+ 0x71, 0x77, 0x99, 0xAD, 0xBC, 0xD5, 0x86, 0xE0,
+ 0xFD, 0x36, 0xF6, 0x35, 0x97, 0x05, 0xEF, 0xB6,
+ 0xFF, 0x83, 0xA7, 0x0F, 0x65, 0xE8, 0x98, 0x8F,
+ 0x42, 0xB0, 0x8B,
+
+ 0x90, 0x2A, 0x6C, 0xF6, 0x1D, 0xD4, 0x36, 0xDD,
+ 0xC3, 0x87, 0x2D, 0xE1, 0x68, 0xED, 0x8F, 0x21,
+ 0x0E, 0x53, 0xF5, 0x03, 0xE9, 0xA0, 0xD5, 0x3A,
+ 0xF9, 0xEF, 0x15, 0xCC, 0x0E, 0xE3, 0xD6, 0x27,
+ 0xB3, 0x30, 0x8B, 0x60, 0x0A, 0x43, 0x2F, 0xA4,
+ 0x41, 0x0E, 0xE9, 0x8F, 0xFD, 0x6E, 0x7C, 0x8A,
+ 0xEA, 0xCB, 0x7F, 0x1E, 0xEF, 0x15, 0x97, 0x59,
+ 0x4A, 0x67, 0x25, 0xFD, 0x72, 0xB6, 0x0D, 0x3A,
+ 0xC0, 0xCE, 0xD4, 0xA7, 0xF6, 0x61, 0x6B, 0x60,
+ 0x8C, 0x55, 0xB3, 0xB7, 0xA9, 0xB0, 0x7E, 0xD8,
+ 0x95, 0xBB, 0xAA, 0xFD, 0x3B, 0x72, 0x40, 0x72,
+ 0x28, 0xA4, 0x73, 0x19, 0x75, 0x37, 0x39, 0x07,
+ 0xBD, 0xB8, 0xB6, 0x51, 0x48, 0xC2, 0xB5, 0xFF,
+ 0xE8, 0xBC, 0x0C, 0x65, 0xD0, 0x8E, 0xB2, 0x32,
+ 0xA5, 0xCE, 0xE7, 0xB9, 0x3C, 0xC2, 0x56, 0xBF,
+ 0x4D, 0x7B, 0x8E, 0xA4, 0xCE, 0x2D, 0x7B, 0x32,
+ 0x48, 0xA9, 0xE3, 0x3A, 0x34, 0x18, 0xB0, 0x6A,
+ 0x68, 0x88, 0xED, 0x55,
+
+ 0xB6, 0xDF, 0x47, 0x88, 0x2F, 0x70, 0x18, 0x3C,
+ 0xB9, 0x72, 0x04, 0x1E, 0x75, 0x5F, 0x45, 0xCA,
+ 0xA4, 0xB0, 0xAC, 0x11, 0x1B, 0x65, 0x4B, 0xAE,
+ 0xCA, 0x4D, 0xA1, 0xA9, 0x2C, 0xDF, 0x76, 0x14,
+ 0x94, 0x2A, 0xFC, 0x04, 0xC2, 0xE8, 0xAE, 0x94,
+ 0x15, 0x11, 0x07, 0x7A, 0x72, 0x25, 0xB6, 0x6D,
+ 0x70, 0x03, 0xC9, 0xAC, 0xE0, 0xAB, 0xD0, 0xC1,
+ 0x90, 0x4E, 0x08, 0xF4, 0x9F, 0x13, 0xB4, 0x7B,
+ 0xB5, 0x56, 0x37, 0x20, 0x83, 0x0C, 0x71, 0xA6,
+ 0x93, 0xF5, 0x00, 0x2F, 0xC9, 0xD5, 0x6A, 0x5C,
+ 0xB7, 0xA7, 0x9E, 0xB2, 0x1B, 0x62, 0x49, 0x9B,
+ 0xA0, 0x2A, 0x54, 0xC5, 0xE4, 0x5C, 0xCF, 0x5A,
+ 0x63, 0x9D, 0xA2, 0x85, 0x8D, 0xFA, 0xEE, 0x2B,
+ 0x1A, 0x41, 0x35, 0x97, 0x67, 0x36, 0x53, 0x25,
+ 0x52, 0x57, 0x8C, 0x8E, 0x53, 0x27, 0x89, 0xBC,
+ 0x2D, 0x3F, 0x91, 0xC4, 0x36, 0xB1, 0xEF, 0x54,
+ 0x1A, 0xCB, 0xDA, 0xC9, 0x78, 0x54, 0x78, 0xBA,
+ 0xDD, 0xA9, 0x23, 0x9D, 0xB4,
+
+ 0xB0, 0xA8, 0x6B, 0x05, 0x72, 0x86, 0xDA, 0xD2,
+ 0x21, 0xDC, 0xC6, 0x3C, 0x0B, 0x47, 0x2E, 0xAA,
+ 0x4A, 0x4F, 0x19, 0x7B, 0xAC, 0xEF, 0x6F, 0xA6,
+ 0xD4, 0x9D, 0x45, 0xEF, 0xB4, 0x14, 0x83, 0x49,
+ 0xA6, 0x20, 0x55, 0x18, 0xA0, 0x64, 0x49, 0xD0,
+ 0xBB, 0x1C, 0xA5, 0x49, 0x56, 0x13, 0x8E, 0xD6,
+ 0x9A, 0x22, 0x3E, 0x1A, 0x28, 0x24, 0x6E, 0x55,
+ 0xAF, 0xA3, 0xDD, 0x02, 0x1B, 0xBC, 0x1E, 0xF2,
+ 0xA7, 0x8A, 0x5C, 0xBD, 0x6A, 0xE8, 0x26, 0x21,
+ 0x81, 0x5D, 0x6C, 0xDF, 0x44, 0xF8, 0xB4, 0xA7,
+ 0x42, 0x9D, 0x73, 0x9A, 0xC4, 0x7A, 0x4B, 0xF2,
+ 0x98, 0xFC, 0xB7, 0xE8, 0xEA, 0x8C, 0x0A, 0xC2,
+ 0xD5, 0xC3, 0x51, 0xCF, 0x3F, 0x71, 0xB5, 0xE4,
+ 0xC3, 0x5B, 0x30, 0xA6, 0xE4, 0x80, 0xFA, 0x46,
+ 0xB4, 0xBC, 0x13, 0x01, 0xA0, 0xA5, 0xF8, 0xEF,
+ 0x6D, 0xA8, 0xD3, 0xCB, 0x92, 0xD7, 0xBF, 0x46,
+ 0x73, 0xC4, 0xE0, 0x12, 0xC3, 0x57, 0xC1, 0x20,
+ 0x5E, 0xF2, 0xF2, 0x7A, 0x18, 0x54,
+
+ 0xD5, 0x8C, 0x8D, 0x9B, 0x33, 0xB8, 0x9B, 0xC3,
+ 0x15, 0x50, 0xC9, 0xC7, 0x25, 0x8B, 0x36, 0xA6,
+ 0x5C, 0x3E, 0x87, 0x59, 0x3F, 0x6B, 0x0A, 0xD8,
+ 0x22, 0x39, 0x48, 0x8A, 0xE4, 0x50, 0x23, 0x8F,
+ 0x3A, 0x6E, 0xE1, 0x60, 0xA3, 0xDE, 0xB3, 0xFA,
+ 0xEA, 0xD4, 0x8B, 0x25, 0x17, 0xB1, 0x4E, 0xBA,
+ 0x0E, 0x97, 0x22, 0x37, 0xEE, 0xFE, 0x5D, 0x42,
+ 0xB5, 0xE5, 0xC1, 0x96, 0x34, 0xA6, 0x0E, 0x11,
+ 0xAA, 0x41, 0xD4, 0xF5, 0xDA, 0x40, 0x22, 0x2B,
+ 0xF9, 0x9E, 0x9C, 0x55, 0x6C, 0xB9, 0x73, 0xDF,
+ 0x94, 0x71, 0x8B, 0x90, 0x91, 0x67, 0xF4, 0xFE,
+ 0x01, 0x90, 0x64, 0xB8, 0xB8, 0x31, 0x85, 0xAE,
+ 0x82, 0x1B, 0x65, 0xD4, 0xC8, 0x61, 0x9D, 0x1D,
+ 0x9A, 0x94, 0x40, 0xD9, 0x7C, 0xE2, 0xE9, 0x09,
+ 0xE9, 0x2B, 0xD0, 0xEB, 0xBE, 0x57, 0xAD, 0x29,
+ 0xCB, 0xA5, 0xD4, 0x46, 0xBA, 0xB6, 0x86, 0xB8,
+ 0xD1, 0x2F, 0x0B, 0xFC, 0xCA, 0x43, 0xBA, 0x60,
+ 0xA2, 0x0F, 0xA6, 0xC6, 0x2F, 0x05, 0x0A,
+
+ 0xA1, 0x11, 0x6A, 0x04, 0xA8, 0x55, 0xB1, 0x04,
+ 0xA8, 0x6F, 0x55, 0x85, 0xE9, 0xF1, 0x0D, 0x6F,
+ 0xDD, 0x04, 0x10, 0x3C, 0xB3, 0xAD, 0xD2, 0x9E,
+ 0xE7, 0x1E, 0x08, 0xBF, 0x65, 0x0A, 0xB0, 0xB4,
+ 0x95, 0x6D, 0xC6, 0x3E, 0xD8, 0x71, 0x46, 0x3E,
+ 0x1B, 0x1E, 0x82, 0x8D, 0x16, 0xF8, 0x98, 0xF1,
+ 0xEC, 0x0B, 0x0C, 0xFB, 0x73, 0xDB, 0x28, 0x1E,
+ 0xC1, 0xD0, 0xC2, 0xB1, 0xB0, 0x48, 0x02, 0xD9,
+ 0x69, 0xC5, 0x72, 0x6D, 0xB2, 0xD2, 0xCE, 0x15,
+ 0x8C, 0x77, 0xAD, 0x48, 0x7C, 0x4D, 0xEA, 0x87,
+ 0x5E, 0x13, 0x6D, 0x61, 0xFE, 0xFC, 0x75, 0xAA,
+ 0x76, 0x55, 0x2E, 0x87, 0x26, 0x92, 0x9D, 0x43,
+ 0x61, 0x7D, 0x1F, 0xFD, 0xE0, 0xCA, 0xC0, 0x87,
+ 0xAF, 0xAF, 0xC4, 0x92, 0x37, 0xED, 0xBB, 0x4F,
+ 0x38, 0x03, 0xE0, 0x1E, 0x1D, 0xB1, 0x4A, 0xBA,
+ 0x9A, 0xA0, 0x14, 0x84, 0x90, 0x90, 0x70, 0x62,
+ 0xA2, 0x55, 0x1D, 0x49, 0xD1, 0x51, 0xF1, 0x9B,
+ 0x1E, 0xD6, 0x8C, 0x02, 0xA4, 0xE2, 0x2D, 0x0E,
+
+ 0xB9, 0xED, 0x83, 0x89, 0xD5, 0x73, 0x97, 0x72,
+ 0x3A, 0xF3, 0x32, 0x9A, 0xC4, 0xE0, 0x80, 0x5B,
+ 0xA3, 0x2E, 0x18, 0x82, 0xD9, 0x6D, 0xDC, 0xA3,
+ 0x4F, 0x00, 0x24, 0x67, 0x52, 0xDC, 0xD9, 0x07,
+ 0x1E, 0x62, 0x1A, 0xC8, 0xA8, 0xC0, 0xEF, 0x68,
+ 0x5E, 0xED, 0x2A, 0x23, 0xA2, 0x91, 0xC4, 0x49,
+ 0x69, 0xF4, 0xC1, 0x84, 0x60, 0x84, 0xAB, 0x34,
+ 0x91, 0x73, 0x76, 0x4A, 0x70, 0x98, 0xD5, 0x42,
+ 0xA0, 0x8C, 0x69, 0x1A, 0x6B, 0xC5, 0x90, 0x86,
+ 0x4E, 0xF3, 0x4C, 0xA0, 0xBA, 0x47, 0x4F, 0x41,
+ 0x0E, 0x83, 0x30, 0xF7, 0x5B, 0x47, 0x4C, 0x2D,
+ 0x78, 0xB9, 0x49, 0x51, 0x54, 0xF4, 0x01, 0x23,
+ 0x77, 0x6D, 0x2D, 0x05, 0x1F, 0xA9, 0xA5, 0x65,
+ 0x83, 0x92, 0xF3, 0xCE, 0x19, 0x2A, 0x9A, 0xF2,
+ 0xC6, 0x9C, 0x08, 0x8D, 0xF9, 0x31, 0xCA, 0xD0,
+ 0xF0, 0x56, 0xB9, 0xD2, 0xDE, 0x09, 0x6E, 0x7B,
+ 0xF1, 0x33, 0x45, 0xAD, 0x5D, 0x20, 0xC9, 0x6B,
+ 0x12, 0x91, 0xCC, 0xA0, 0x44, 0xF3, 0xB2, 0x9C,
+ 0x29,
+
+ 0x28, 0x3B, 0xFC, 0xF7, 0x0B, 0xE0, 0x62, 0x2F,
+ 0xB3, 0x2E, 0x10, 0xD3, 0x78, 0x0C, 0x33, 0x6D,
+ 0xD7, 0xA8, 0xB2, 0xF7, 0x1C, 0x6C, 0xBA, 0xD0,
+ 0x67, 0x5F, 0xB5, 0xD3, 0x71, 0x09, 0xD7, 0x34,
+ 0xCE, 0xFB, 0xF0, 0xEE, 0x7D, 0x5C, 0xCE, 0x03,
+ 0x20, 0x85, 0xEA, 0xD6, 0x01, 0xF9, 0x4A, 0x3C,
+ 0x83, 0xC8, 0x59, 0xA3, 0x42, 0x90, 0xB3, 0x14,
+ 0x04, 0x86, 0xB1, 0x1A, 0xDB, 0x7C, 0x35, 0x56,
+ 0x96, 0x15, 0xE4, 0x17, 0x27, 0xB0, 0x47, 0xF2,
+ 0x75, 0x4E, 0xBD, 0x4D, 0x6D, 0x40, 0xDB, 0x03,
+ 0xBE, 0x34, 0x23, 0x9C, 0x80, 0xF3, 0x34, 0xF2,
+ 0x89, 0x43, 0xE2, 0x39, 0x4B, 0x9B, 0xD9, 0x1A,
+ 0xAB, 0x48, 0x4A, 0x97, 0x66, 0x87, 0xF8, 0x37,
+ 0x70, 0xCC, 0x05, 0x24, 0x48, 0x9F, 0xEF, 0x19,
+ 0x9C, 0xB4, 0x5F, 0x76, 0x28, 0xED, 0x59, 0x12,
+ 0x50, 0x5B, 0x69, 0x44, 0xA9, 0xBE, 0x40, 0xEE,
+ 0x2C, 0x97, 0xA3, 0x4A, 0x05, 0xCC, 0x57, 0xB8,
+ 0xC9, 0x26, 0x85, 0xE4, 0xB1, 0x58, 0xF2, 0x4D,
+ 0x9B, 0xA9,
+
+ 0x36, 0xEF, 0xE2, 0x4F, 0xAE, 0x4C, 0xB1, 0xB3,
+ 0xB8, 0x22, 0x91, 0xB6, 0xC5, 0x31, 0x60, 0xFF,
+ 0x7B, 0x00, 0x71, 0x12, 0xAA, 0x5A, 0xD2, 0x10,
+ 0x5E, 0x0F, 0x4C, 0xB0, 0xDB, 0x09, 0x11, 0xC7,
+ 0x28, 0x6C, 0x88, 0x96, 0x97, 0xC6, 0xB7, 0x56,
+ 0x77, 0x20, 0xAB, 0xE4, 0x03, 0xFA, 0x7A, 0xCF,
+ 0x8E, 0xB7, 0x73, 0xEB, 0xD6, 0x80, 0xD8, 0xAE,
+ 0x6F, 0xCC, 0x22, 0x90, 0x49, 0x7B, 0x21, 0x57,
+ 0xAF, 0x39, 0x8E, 0x25, 0x98, 0x54, 0x2C, 0x7A,
+ 0xFC, 0xF1, 0xAE, 0xA0, 0xD7, 0x69, 0x95, 0x04,
+ 0x6A, 0x93, 0xDA, 0x41, 0x8F, 0xE3, 0x53, 0x7D,
+ 0x8C, 0xC4, 0xE6, 0x14, 0xD6, 0xF5, 0x23, 0x10,
+ 0xFF, 0xF4, 0x3D, 0x87, 0x8E, 0x44, 0x7B, 0xBD,
+ 0xDF, 0x5B, 0x81, 0x1E, 0x88, 0x9C, 0x8E, 0x3C,
+ 0xB3, 0xA1, 0x8D, 0xC9, 0x1F, 0xE2, 0x51, 0xFB,
+ 0x31, 0xBA, 0x07, 0x2D, 0xF8, 0xFA, 0x54, 0x88,
+ 0x64, 0x00, 0xA0, 0x73, 0x2A, 0xD7, 0x9B, 0x85,
+ 0xBB, 0xED, 0x0A, 0x2E, 0xA1, 0x98, 0x3D, 0x87,
+ 0xFA, 0x0A, 0x43,
+
+ 0xAE, 0x78, 0x23, 0x96, 0x97, 0xE1, 0x6D, 0x02,
+ 0x31, 0xA9, 0x56, 0xBA, 0xDC, 0xA4, 0xDB, 0xD5,
+ 0x5F, 0x37, 0x26, 0xF8, 0xED, 0x78, 0x79, 0xAA,
+ 0x7B, 0xCC, 0xC3, 0x67, 0x38, 0x86, 0xB6, 0x58,
+ 0x7D, 0x2A, 0x5E, 0x77, 0xF8, 0xDB, 0x3A, 0xB0,
+ 0xB3, 0x83, 0x3A, 0xEF, 0xB5, 0xB0, 0x46, 0xA7,
+ 0x85, 0x98, 0xA8, 0x71, 0x1C, 0x2C, 0xB6, 0x06,
+ 0x3F, 0xEC, 0x59, 0x78, 0x15, 0xAD, 0x17, 0x65,
+ 0x94, 0x37, 0xC1, 0x21, 0xC9, 0x1A, 0x16, 0xEA,
+ 0x1A, 0xFE, 0x3D, 0x35, 0xF4, 0xBA, 0x5D, 0xA0,
+ 0x21, 0x9C, 0x89, 0x39, 0x69, 0xAB, 0x8E, 0x4B,
+ 0x8A, 0x9C, 0x38, 0xFD, 0x53, 0x37, 0xB4, 0x59,
+ 0xBE, 0xB0, 0x56, 0xD7, 0x6C, 0xF8, 0xB8, 0xF1,
+ 0x03, 0x26, 0xF5, 0x07, 0x98, 0xDB, 0xDF, 0xF3,
+ 0x9D, 0x02, 0x65, 0x78, 0x7C, 0xD7, 0x71, 0x06,
+ 0x93, 0xFF, 0xFA, 0xBE, 0xEF, 0x24, 0x24, 0x21,
+ 0x32, 0xD8, 0xC2, 0xFD, 0xB9, 0x08, 0xBC, 0x06,
+ 0xD6, 0xC1, 0xEE, 0x5D, 0xFE, 0xA1, 0x8D, 0x12,
+ 0x9A, 0x36, 0x5B, 0xB7,
+
+ 0x61, 0x61, 0x14, 0x68, 0xE4, 0x54, 0x04, 0x1F,
+ 0xB4, 0x42, 0x87, 0x44, 0x7B, 0x01, 0xC6, 0xD6,
+ 0xF9, 0xBC, 0xE5, 0x1D, 0x25, 0x6E, 0xFB, 0xC9,
+ 0x2A, 0x50, 0x31, 0xB7, 0x8B, 0x11, 0x50, 0x39,
+ 0x2C, 0xE9, 0x37, 0xD1, 0x43, 0xD5, 0xD2, 0x9D,
+ 0x9D, 0x9E, 0x58, 0x1C, 0x14, 0x90, 0x8C, 0x0B,
+ 0xF0, 0x2D, 0xBE, 0xEB, 0xF4, 0x24, 0xA9, 0xFF,
+ 0x07, 0x5C, 0x8F, 0x49, 0x26, 0xEF, 0xC4, 0x74,
+ 0x8E, 0x32, 0x03, 0xCA, 0xBF, 0xB9, 0x8D, 0x3C,
+ 0x69, 0xE4, 0x3D, 0x35, 0x85, 0xC3, 0xAE, 0x35,
+ 0x33, 0x95, 0xD4, 0xE8, 0xAC, 0xBE, 0xE2, 0x2E,
+ 0xD2, 0x75, 0x3A, 0x42, 0x00, 0xBF, 0xC2, 0x61,
+ 0xF1, 0x0C, 0x5D, 0xFB, 0xC9, 0x59, 0xB1, 0xAC,
+ 0x37, 0x83, 0x7E, 0x52, 0xB0, 0x32, 0x38, 0x9E,
+ 0xD5, 0xCD, 0xE4, 0x77, 0x47, 0x08, 0x9B, 0x41,
+ 0x2A, 0x5D, 0xA7, 0x5E, 0xAA, 0xF2, 0xD3, 0x4F,
+ 0x76, 0x20, 0xB3, 0xD5, 0x55, 0xEE, 0x41, 0x00,
+ 0x8C, 0x7C, 0x38, 0x67, 0xF4, 0x38, 0x21, 0xB8,
+ 0x3F, 0x1E, 0x57, 0x46, 0x45,
+
+ 0x66, 0xF1, 0x58, 0xCA, 0xD3, 0x81, 0x9F, 0x85,
+ 0x1D, 0x6F, 0xA2, 0xB5, 0xCB, 0x77, 0x12, 0x4C,
+ 0x41, 0xF2, 0x93, 0xED, 0x56, 0x04, 0xC7, 0xB1,
+ 0xA0, 0x9B, 0x6D, 0x51, 0x9C, 0xC8, 0xE9, 0xF3,
+ 0x9C, 0xE1, 0xC2, 0x91, 0x6A, 0x31, 0x05, 0x2A,
+ 0xB1, 0xEE, 0x19, 0xCD, 0x01, 0x30, 0x2F, 0x80,
+ 0x37, 0x03, 0xCD, 0xB1, 0x7D, 0xB8, 0xC0, 0x06,
+ 0x83, 0x00, 0xC7, 0x12, 0x85, 0x43, 0x8D, 0x67,
+ 0x12, 0xD8, 0xC8, 0x15, 0x62, 0x80, 0xA1, 0xE1,
+ 0x60, 0x42, 0x04, 0x74, 0x34, 0xBA, 0xBC, 0x67,
+ 0xF0, 0x04, 0xA7, 0x54, 0x3C, 0x6C, 0x0B, 0x10,
+ 0x2E, 0x02, 0x4D, 0x4F, 0x4A, 0x45, 0x97, 0x8E,
+ 0xF6, 0x50, 0x65, 0x44, 0xD0, 0x8B, 0x72, 0x33,
+ 0xCE, 0xD9, 0xDE, 0x7A, 0xE9, 0x98, 0x6F, 0x0C,
+ 0xE7, 0x79, 0xA8, 0x11, 0x73, 0x83, 0xF2, 0x93,
+ 0x5B, 0xE7, 0x3E, 0x4B, 0x81, 0xCE, 0xFB, 0x4E,
+ 0x27, 0x73, 0x7E, 0x66, 0xFA, 0x55, 0x1F, 0xCE,
+ 0xE8, 0xC3, 0x38, 0x7D, 0x04, 0xC6, 0xC3, 0x30,
+ 0x47, 0x8B, 0x02, 0x9D, 0x81, 0x49,
+
+ 0x0A, 0x2A, 0x5B, 0x2B, 0x5E, 0xA4, 0x2B, 0x40,
+ 0x5E, 0x95, 0x70, 0x40, 0x23, 0x66, 0xD1, 0x1A,
+ 0x27, 0x79, 0x3F, 0x3C, 0xA9, 0x86, 0xF2, 0x75,
+ 0x2A, 0x52, 0x2E, 0xFE, 0x4E, 0x8E, 0x7E, 0x20,
+ 0x79, 0x19, 0x98, 0xDD, 0x01, 0x3F, 0x19, 0x68,
+ 0x23, 0x0A, 0xF0, 0x18, 0xA7, 0x13, 0x33, 0xF3,
+ 0x9E, 0x04, 0xA7, 0xA9, 0x01, 0xFA, 0xAC, 0xF3,
+ 0x81, 0x3D, 0xC6, 0x57, 0x35, 0x8C, 0xFE, 0x5D,
+ 0xCB, 0xE6, 0xF3, 0xA6, 0xCF, 0x18, 0x96, 0x70,
+ 0xCF, 0xAD, 0x05, 0xC6, 0x75, 0x05, 0x02, 0x50,
+ 0xA6, 0xAA, 0x88, 0xBC, 0x57, 0xA9, 0x14, 0x1A,
+ 0xF9, 0x1A, 0xD3, 0x40, 0xC7, 0x48, 0xFF, 0xE0,
+ 0x2D, 0xC6, 0xA8, 0x94, 0xBA, 0x3F, 0xFA, 0x76,
+ 0x44, 0xBA, 0xE8, 0x3E, 0xCC, 0x0D, 0x16, 0x8A,
+ 0x72, 0x91, 0xD8, 0xB1, 0x29, 0xC7, 0x3C, 0x67,
+ 0x1E, 0xA2, 0x3A, 0x9C, 0x9F, 0x5B, 0xCD, 0x41,
+ 0x8C, 0xCB, 0xFF, 0xFE, 0x70, 0x6F, 0xDA, 0xDF,
+ 0x10, 0x4B, 0xFF, 0x9A, 0xBF, 0x3E, 0xFF, 0x98,
+ 0x4E, 0x62, 0x15, 0x96, 0x97, 0xE1, 0x4E,
+
+ 0x18, 0xDD, 0xC6, 0xD7, 0x31, 0x4C, 0x44, 0xF5,
+ 0x63, 0x56, 0x9C, 0xDF, 0xDC, 0x2D, 0x25, 0x5A,
+ 0xBF, 0x0C, 0x40, 0x69, 0x86, 0xDA, 0xA8, 0x76,
+ 0x86, 0x9C, 0x74, 0x9F, 0xDD, 0x04, 0x01, 0x9E,
+ 0x0B, 0x70, 0xEF, 0xE1, 0xF6, 0x26, 0x58, 0x5F,
+ 0x10, 0x2F, 0x9D, 0xC7, 0xAC, 0x4C, 0x19, 0x85,
+ 0xC8, 0x3E, 0xE8, 0xFF, 0xC4, 0x6C, 0x17, 0xB0,
+ 0xB9, 0x2E, 0x00, 0xD6, 0xEA, 0xF0, 0xFA, 0x40,
+ 0x93, 0x8D, 0x6F, 0xFD, 0x0B, 0xF5, 0x59, 0xEC,
+ 0xEA, 0x64, 0x26, 0x9D, 0x5F, 0xB2, 0x26, 0x1E,
+ 0x4C, 0xC8, 0x65, 0xAD, 0xD4, 0xC1, 0xAD, 0x63,
+ 0x29, 0x6C, 0x11, 0xCB, 0xE6, 0xDC, 0xF8, 0x2E,
+ 0x18, 0xA7, 0x50, 0xF0, 0x8F, 0x0E, 0x9B, 0x95,
+ 0xCC, 0x74, 0x3D, 0xB1, 0x9C, 0xD3, 0x50, 0x08,
+ 0x18, 0x5E, 0x27, 0x15, 0xD3, 0xF3, 0x5A, 0xC0,
+ 0x63, 0xEC, 0xB1, 0x4C, 0x77, 0x77, 0x9B, 0xE9,
+ 0x7B, 0x57, 0x0C, 0x31, 0xAA, 0xB5, 0xCE, 0x6C,
+ 0x4F, 0x46, 0x16, 0x0D, 0x55, 0xB9, 0x36, 0xF1,
+ 0xFA, 0x36, 0xE8, 0x89, 0xB0, 0x7B, 0xBB, 0x84,
+
+ 0xF3, 0x24, 0x87, 0xDA, 0x52, 0xDC, 0x22, 0x0A,
+ 0xE1, 0x8E, 0x6A, 0x1A, 0xA6, 0x6C, 0x16, 0x48,
+ 0xFD, 0x70, 0xF9, 0x3E, 0x45, 0xF7, 0xE3, 0x6A,
+ 0xAC, 0x92, 0x5A, 0x82, 0xD1, 0xC3, 0x8C, 0x7E,
+ 0x76, 0x69, 0x3E, 0x34, 0x66, 0x25, 0x46, 0xD0,
+ 0x17, 0xEE, 0x25, 0xD2, 0xB2, 0x2A, 0xCE, 0xB8,
+ 0x6A, 0x56, 0x2C, 0x37, 0xB0, 0x51, 0x62, 0x1A,
+ 0x04, 0xB9, 0x68, 0xAA, 0x9B, 0x30, 0xEE, 0x17,
+ 0x57, 0xFC, 0x98, 0xCF, 0x7E, 0x4B, 0xAB, 0x25,
+ 0xA0, 0x91, 0x6E, 0x68, 0x23, 0x55, 0xF0, 0xC7,
+ 0x20, 0xA7, 0x3B, 0xE1, 0x03, 0xB3, 0x94, 0x2C,
+ 0x5D, 0xC1, 0x50, 0x32, 0x61, 0xB8, 0x63, 0x69,
+ 0x61, 0x74, 0x61, 0xCA, 0xC1, 0x49, 0x25, 0x63,
+ 0x9B, 0xA1, 0x5A, 0x09, 0x23, 0x44, 0x05, 0x97,
+ 0xCA, 0x73, 0xA6, 0x57, 0x92, 0xA5, 0x22, 0x18,
+ 0x82, 0x55, 0x0E, 0xFF, 0xE7, 0x53, 0xA9, 0x71,
+ 0x25, 0xC6, 0x2D, 0x02, 0x07, 0xD4, 0x51, 0x12,
+ 0x18, 0x03, 0x71, 0x4F, 0x10, 0x23, 0x17, 0xF0,
+ 0x76, 0xB3, 0x3B, 0x57, 0x8D, 0x88, 0xDA, 0x6F,
+ 0x5F,
+
+ 0xCB, 0xF5, 0x44, 0xA5, 0x45, 0x49, 0x7D, 0x58,
+ 0xA6, 0x10, 0x4B, 0x4E, 0x81, 0xF2, 0x15, 0x21,
+ 0x03, 0xFB, 0xD2, 0x34, 0xE2, 0xF8, 0x99, 0x09,
+ 0x5D, 0x59, 0x24, 0xFF, 0xB9, 0x0D, 0xBC, 0xF6,
+ 0x2B, 0x11, 0x55, 0x4D, 0x50, 0x7C, 0xCD, 0x18,
+ 0x94, 0x92, 0xF3, 0x5C, 0x95, 0x7A, 0x64, 0xF7,
+ 0x35, 0x27, 0x56, 0x79, 0xD6, 0xD8, 0x81, 0xE0,
+ 0xF3, 0x3F, 0x80, 0x8F, 0x97, 0x1B, 0xD8, 0x15,
+ 0x70, 0x15, 0x2D, 0xC0, 0x2E, 0x7E, 0x79, 0xF8,
+ 0x1F, 0x88, 0xB7, 0xB7, 0xFF, 0x53, 0x67, 0xE8,
+ 0xC1, 0x59, 0x89, 0x66, 0xFD, 0x66, 0x4E, 0x88,
+ 0xA0, 0xCD, 0xC6, 0xD0, 0x34, 0x0C, 0x31, 0xE3,
+ 0xD4, 0x5F, 0x32, 0x32, 0xAC, 0xCC, 0xE1, 0x24,
+ 0x8C, 0x4E, 0xC9, 0x39, 0xC3, 0x7A, 0x6B, 0xAB,
+ 0xAE, 0x6C, 0x01, 0x79, 0x6D, 0xB4, 0xAF, 0x49,
+ 0x12, 0x10, 0xB3, 0xC5, 0x20, 0xB9, 0x63, 0x99,
+ 0x79, 0xC1, 0x22, 0xE4, 0x74, 0x15, 0x42, 0x61,
+ 0x98, 0x4E, 0xDC, 0x13, 0xD0, 0xE1, 0xD8, 0x24,
+ 0x0A, 0xC5, 0xB4, 0x54, 0xDC, 0x3C, 0x00, 0xDE,
+ 0xFB, 0xEB,
+
+ 0x01, 0x0B, 0xD7, 0x6A, 0x19, 0xF8, 0xD2, 0x4A,
+ 0xD6, 0xC8, 0xFA, 0x05, 0x69, 0x4A, 0x18, 0x97,
+ 0x35, 0x61, 0x8B, 0xB9, 0x8B, 0x7B, 0x0C, 0xD9,
+ 0xF4, 0xF4, 0xC4, 0x2F, 0x1F, 0xA9, 0x98, 0x16,
+ 0xB7, 0xD6, 0x1F, 0x4A, 0x59, 0x42, 0x37, 0x60,
+ 0x37, 0x20, 0x37, 0x5C, 0x16, 0x6E, 0x63, 0x49,
+ 0x25, 0x1A, 0x86, 0x42, 0x00, 0xC3, 0x4A, 0x33,
+ 0xC7, 0x7D, 0x06, 0x14, 0xC9, 0x98, 0x19, 0x9A,
+ 0xD3, 0x17, 0xB4, 0x61, 0x4F, 0x52, 0x09, 0x13,
+ 0x54, 0xFE, 0xE4, 0x47, 0xA4, 0xFF, 0xA5, 0x20,
+ 0x62, 0x52, 0xB1, 0xDD, 0x42, 0xF2, 0x1C, 0xE9,
+ 0x0E, 0x2D, 0xEA, 0x19, 0x51, 0xF5, 0x3E, 0x7D,
+ 0x27, 0xFF, 0x1D, 0x43, 0x96, 0x16, 0x9B, 0xBD,
+ 0x9D, 0x29, 0x0E, 0x19, 0x4B, 0x6E, 0x98, 0xF4,
+ 0xA3, 0x51, 0x3C, 0x14, 0x64, 0xBF, 0x93, 0xAA,
+ 0x3C, 0x86, 0xF8, 0xB5, 0x3A, 0x2C, 0x12, 0x10,
+ 0x52, 0xD6, 0xE9, 0xB6, 0x36, 0x91, 0x5B, 0x36,
+ 0x22, 0x9B, 0xD1, 0x00, 0xEC, 0xC6, 0x13, 0x13,
+ 0x1D, 0x83, 0xF4, 0xF9, 0xBE, 0xC0, 0x3E, 0x71,
+ 0x0B, 0x64, 0xDF,
+
+ 0xF2, 0xB0, 0xFC, 0xD2, 0x54, 0x85, 0x18, 0xD4,
+ 0x31, 0x7A, 0x3E, 0xD5, 0xDD, 0x8D, 0x3C, 0xCC,
+ 0x4E, 0x92, 0x14, 0xE4, 0x21, 0x39, 0xF3, 0x73,
+ 0x66, 0x71, 0x77, 0x29, 0x37, 0x49, 0x6C, 0x72,
+ 0xFB, 0x51, 0x17, 0x6C, 0x9E, 0x4A, 0x7C, 0x8C,
+ 0xBF, 0x96, 0x13, 0x8F, 0xAE, 0x7E, 0x88, 0x15,
+ 0xE9, 0x5E, 0x1A, 0xC4, 0xA7, 0x42, 0xFA, 0x60,
+ 0xD5, 0xFB, 0xCF, 0x90, 0x56, 0x97, 0xBB, 0xAD,
+ 0xF2, 0x2C, 0x6B, 0x07, 0xA5, 0xE6, 0x99, 0x92,
+ 0x75, 0x55, 0x69, 0xE8, 0xA3, 0xD9, 0x05, 0xC4,
+ 0x95, 0xED, 0xD0, 0x8E, 0x18, 0x60, 0x86, 0x86,
+ 0xEB, 0xC3, 0x20, 0xA8, 0xB9, 0x2E, 0xB8, 0x38,
+ 0xEB, 0xCE, 0x48, 0x2E, 0x4B, 0x42, 0xD6, 0xFB,
+ 0xDF, 0x97, 0xC4, 0xCD, 0x8C, 0xFD, 0x98, 0x0E,
+ 0xAC, 0xC2, 0xC4, 0xDA, 0x07, 0xFF, 0x8D, 0x72,
+ 0xF3, 0x15, 0x6F, 0x69, 0x3A, 0x61, 0x5F, 0xE0,
+ 0xAE, 0x1B, 0xCB, 0x16, 0x91, 0xEF, 0x54, 0x92,
+ 0xFC, 0xCD, 0xAF, 0xF4, 0x45, 0x4F, 0x2A, 0xCD,
+ 0xF8, 0xE4, 0x3F, 0x99, 0x2C, 0x61, 0xEC, 0x23,
+ 0xE3, 0x8B, 0xAB, 0x8F,
+
+ 0x7C, 0x3F, 0x27, 0xDE, 0xAF, 0xE9, 0x72, 0x9C,
+ 0x04, 0xDA, 0xB4, 0xBB, 0xE6, 0x6F, 0x56, 0xF1,
+ 0xE8, 0x7E, 0xB5, 0xDA, 0x14, 0x2D, 0xFA, 0x29,
+ 0x80, 0x87, 0x53, 0x78, 0x65, 0xF7, 0x98, 0x64,
+ 0xB7, 0x11, 0x1A, 0x08, 0x4F, 0x36, 0x7E, 0xF8,
+ 0x4F, 0x0C, 0x70, 0xFE, 0xAF, 0xF1, 0x72, 0xC9,
+ 0xB8, 0x39, 0x57, 0xCB, 0x10, 0x61, 0x95, 0x49,
+ 0xEA, 0xB4, 0x2B, 0xA0, 0x77, 0x76, 0x30, 0x5D,
+ 0x9A, 0xB5, 0xCB, 0xF4, 0x5F, 0xC7, 0xA6, 0xD8,
+ 0x3A, 0x9E, 0xA8, 0xA1, 0x9F, 0xAB, 0xCC, 0x2C,
+ 0x2D, 0x8C, 0xCF, 0x3D, 0x7C, 0x11, 0xC6, 0xE9,
+ 0xD5, 0x15, 0xA2, 0xB8, 0xCE, 0x11, 0x45, 0x52,
+ 0x94, 0x0D, 0xE3, 0xF4, 0x47, 0x4A, 0xC6, 0x2E,
+ 0x7A, 0xBF, 0xBB, 0x4D, 0x2A, 0x89, 0xE5, 0x49,
+ 0x51, 0xDE, 0x25, 0x36, 0x58, 0x52, 0x3F, 0xA3,
+ 0xAD, 0xFE, 0xE3, 0xA3, 0x31, 0x90, 0xDA, 0xA3,
+ 0x1D, 0x48, 0xD6, 0xE8, 0xF2, 0x9E, 0x4C, 0xEC,
+ 0xCA, 0xC7, 0x46, 0x3C, 0xD5, 0x89, 0x01, 0xA7,
+ 0x33, 0xD3, 0x50, 0x7E, 0x31, 0x1C, 0x8E, 0xFF,
+ 0xF0, 0xB4, 0x42, 0x70, 0xA5,
+
+ 0xDB, 0xFD, 0x65, 0xEB, 0x8C, 0xA7, 0x97, 0xE5,
+ 0xC7, 0xF4, 0x2E, 0xD4, 0x19, 0xCD, 0xA6, 0x0F,
+ 0x56, 0x39, 0xE3, 0x55, 0xF6, 0xFA, 0x43, 0xAC,
+ 0x3C, 0x0A, 0x1E, 0x00, 0xBF, 0x36, 0x1B, 0x95,
+ 0x71, 0x7E, 0x73, 0xBF, 0x93, 0x76, 0xF6, 0x2D,
+ 0xCB, 0x35, 0xBE, 0x43, 0x33, 0x2B, 0x89, 0x2D,
+ 0x85, 0x8A, 0xCE, 0x2F, 0xE7, 0x9C, 0x39, 0xD7,
+ 0x01, 0x69, 0x2E, 0xB3, 0xE7, 0xED, 0xEF, 0x41,
+ 0x06, 0xE7, 0xFC, 0x1F, 0x4B, 0x42, 0x71, 0xB2,
+ 0x59, 0x55, 0xEB, 0xBD, 0x18, 0x12, 0x63, 0x7F,
+ 0xEE, 0x10, 0x35, 0x84, 0x4E, 0x58, 0x9C, 0x75,
+ 0x86, 0xAB, 0x7F, 0x54, 0x8C, 0x90, 0x79, 0xAD,
+ 0xE7, 0xA6, 0x40, 0xCA, 0xB3, 0x6D, 0x8A, 0x14,
+ 0x8A, 0xE5, 0x13, 0x8C, 0x6E, 0xE9, 0x99, 0x56,
+ 0x11, 0xFC, 0xD4, 0x3B, 0xF5, 0xCB, 0x65, 0x33,
+ 0xEF, 0x98, 0x63, 0x7F, 0x91, 0x22, 0xD1, 0x2E,
+ 0xF4, 0xE0, 0xB3, 0xE8, 0xA6, 0x9E, 0xF9, 0x10,
+ 0xC6, 0xF1, 0x21, 0x95, 0x8C, 0x34, 0x2D, 0x7C,
+ 0x54, 0x92, 0x8D, 0x8F, 0xB6, 0x03, 0x34, 0xF7,
+ 0xF7, 0xD8, 0x5A, 0xBA, 0x57, 0x50,
+
+ 0x41, 0x62, 0x0B, 0xC6, 0xC6, 0x43, 0xE4, 0x2D,
+ 0x36, 0x29, 0x87, 0x1D, 0x0D, 0xAC, 0xDB, 0xF0,
+ 0x00, 0x89, 0xBD, 0xE6, 0x48, 0x04, 0x24, 0x0C,
+ 0x28, 0x54, 0x88, 0x94, 0x3E, 0x1F, 0x2F, 0x5D,
+ 0x1C, 0xC1, 0x18, 0x38, 0xA6, 0xA5, 0xCA, 0xC3,
+ 0xAF, 0x5C, 0xDF, 0xAD, 0x8B, 0x4F, 0x53, 0x9E,
+ 0x6B, 0x99, 0xAB, 0x09, 0x2F, 0xD8, 0x11, 0xF9,
+ 0xC9, 0xAB, 0x73, 0x0A, 0xE6, 0x50, 0x6F, 0xBD,
+ 0xA5, 0xD1, 0x16, 0xFE, 0xC3, 0x11, 0xDE, 0x11,
+ 0x72, 0xC4, 0x71, 0x80, 0x40, 0x02, 0x14, 0x1F,
+ 0xC1, 0x6C, 0xE3, 0x28, 0xF8, 0xD8, 0x99, 0x06,
+ 0x1B, 0x90, 0x55, 0xFB, 0x67, 0x1D, 0x37, 0xA8,
+ 0xF9, 0xC7, 0xB2, 0xAD, 0x0F, 0x6C, 0xF4, 0x0F,
+ 0x1B, 0x42, 0xBD, 0x57, 0x51, 0x56, 0xA5, 0x83,
+ 0x7A, 0x15, 0x1C, 0x1A, 0xCF, 0x8C, 0xA4, 0x1B,
+ 0xF2, 0xFB, 0xDF, 0xC1, 0xCE, 0xD1, 0xF3, 0x29,
+ 0x7B, 0xA6, 0xA7, 0xE8, 0xA8, 0xB4, 0xCF, 0xEC,
+ 0x4E, 0xD7, 0x92, 0x82, 0x3A, 0x27, 0x05, 0xEF,
+ 0x88, 0x1B, 0x9C, 0x04, 0xAD, 0xF9, 0x51, 0x94,
+ 0xA6, 0xC1, 0xF8, 0x16, 0x3F, 0x5F, 0xF2,
+
+ 0xFC, 0xF4, 0xBD, 0x0F, 0xE9, 0x09, 0xA4, 0xCE,
+ 0x31, 0x2D, 0x53, 0xD4, 0x15, 0xE5, 0x62, 0xF6,
+ 0x72, 0x63, 0x22, 0x53, 0x93, 0x2E, 0xCB, 0x30,
+ 0x01, 0x5C, 0x1C, 0xBA, 0x04, 0xA6, 0x95, 0x46,
+ 0x4E, 0x03, 0xEC, 0x36, 0xA2, 0xBE, 0x86, 0xD7,
+ 0x6E, 0x92, 0x2C, 0xEF, 0x64, 0x45, 0x94, 0x22,
+ 0xF8, 0x11, 0x43, 0x2D, 0x81, 0x04, 0xE6, 0x7B,
+ 0xEC, 0xE3, 0xF9, 0x9A, 0x43, 0xEF, 0xA7, 0xC9,
+ 0x5F, 0x39, 0x56, 0x6D, 0x3A, 0xBC, 0x26, 0xCD,
+ 0x77, 0x6F, 0x38, 0x30, 0x0A, 0x78, 0xD3, 0x98,
+ 0x71, 0xE1, 0x2C, 0xEA, 0xC2, 0xD8, 0x69, 0x18,
+ 0x74, 0xFE, 0x91, 0x1C, 0xAF, 0x5D, 0x8D, 0xDB,
+ 0x59, 0xDA, 0x52, 0xCD, 0xE4, 0x0D, 0x76, 0x41,
+ 0x9E, 0x6C, 0xD3, 0x85, 0x96, 0x3C, 0x8E, 0x66,
+ 0xDF, 0xED, 0x26, 0x03, 0x84, 0x88, 0x9D, 0x25,
+ 0x39, 0x35, 0xAD, 0xB5, 0x8B, 0xBB, 0xC5, 0x64,
+ 0xCE, 0xC5, 0xD7, 0x88, 0x5C, 0x2D, 0x46, 0x47,
+ 0x80, 0x11, 0x43, 0x85, 0xF1, 0xEB, 0x90, 0x71,
+ 0xA4, 0xB7, 0x5A, 0x3B, 0xB4, 0x51, 0x68, 0x76,
+ 0x63, 0x4D, 0x8F, 0x9F, 0x65, 0x6F, 0x9D, 0x03,
+
+ 0x80, 0x5F, 0x0F, 0xB1, 0x39, 0x5B, 0xF6, 0x33,
+ 0xF7, 0x1C, 0xE6, 0x3C, 0x31, 0xC4, 0x31, 0x1A,
+ 0x14, 0x67, 0x38, 0x6C, 0x79, 0x59, 0x05, 0xF2,
+ 0x1F, 0xBA, 0xF2, 0xAE, 0x0C, 0xFF, 0xC5, 0x22,
+ 0x89, 0xB9, 0x2C, 0x88, 0xD1, 0x10, 0x24, 0xD1,
+ 0xBA, 0xD4, 0xD7, 0x41, 0x45, 0xAF, 0x57, 0xFC,
+ 0xF6, 0x97, 0x81, 0x4D, 0xA5, 0xF9, 0xC2, 0x25,
+ 0xFC, 0x3B, 0xBD, 0x0E, 0x96, 0xC2, 0x8B, 0xE3,
+ 0x93, 0x67, 0x65, 0xC4, 0x1D, 0x2A, 0x86, 0xCC,
+ 0x8A, 0x87, 0x4C, 0x35, 0xF7, 0x55, 0x51, 0xD6,
+ 0x8A, 0x8A, 0xE8, 0xE8, 0x69, 0xEF, 0x1A, 0xED,
+ 0xCB, 0x09, 0x4C, 0xE1, 0x4F, 0x36, 0xA6, 0xBD,
+ 0x68, 0x6B, 0x87, 0xC1, 0x39, 0x5E, 0x63, 0x61,
+ 0xA7, 0x19, 0x60, 0x3E, 0x1A, 0x2A, 0xF0, 0x43,
+ 0xA4, 0xE5, 0xE3, 0xEF, 0x76, 0x20, 0xA1, 0x7D,
+ 0x61, 0xFB, 0xC0, 0x8D, 0xED, 0xB0, 0x78, 0xDB,
+ 0xEC, 0x53, 0x44, 0x4A, 0x94, 0x42, 0x39, 0x83,
+ 0x41, 0x49, 0xBC, 0xA5, 0x17, 0x6C, 0xB4, 0x89,
+ 0x8D, 0xAB, 0x32, 0x40, 0x05, 0x69, 0x44, 0xF8,
+ 0x9A, 0x8B, 0x60, 0xD5, 0x47, 0x31, 0xD5, 0x17,
+ 0x1A,
+
+ 0x99, 0xC8, 0x1F, 0x50, 0x51, 0xE0, 0xCA, 0x64,
+ 0x60, 0x38, 0x24, 0x34, 0x8B, 0x37, 0x13, 0x87,
+ 0x05, 0xE5, 0x3D, 0x7E, 0x8F, 0x8D, 0xF7, 0xD5,
+ 0x92, 0x06, 0xA4, 0x32, 0xD9, 0x64, 0xD8, 0xFC,
+ 0x1B, 0x5E, 0x46, 0xE4, 0x97, 0x14, 0x80, 0x2D,
+ 0xE2, 0x7B, 0x2E, 0xC4, 0xC2, 0x50, 0x0C, 0xDC,
+ 0xC1, 0xE6, 0x6A, 0x5F, 0x37, 0x02, 0x36, 0x24,
+ 0x98, 0x51, 0xB5, 0x92, 0x4E, 0x95, 0x80, 0x3E,
+ 0x93, 0x21, 0x03, 0xFB, 0x41, 0x20, 0x85, 0x55,
+ 0x39, 0xFC, 0xFC, 0x9E, 0xE6, 0x5B, 0x21, 0x29,
+ 0xC6, 0xCD, 0x63, 0x6B, 0xB8, 0x66, 0xB3, 0xB2,
+ 0x77, 0xE6, 0xA3, 0x3A, 0x40, 0x6C, 0xD0, 0x7C,
+ 0xEA, 0x36, 0x5F, 0x3E, 0xA2, 0x47, 0x64, 0xD9,
+ 0xF5, 0x94, 0x09, 0xE6, 0xC4, 0x90, 0x0E, 0xF6,
+ 0x5E, 0xE5, 0x9E, 0x54, 0xFC, 0x32, 0x51, 0x0F,
+ 0xED, 0x6A, 0xEE, 0x50, 0x29, 0x47, 0x0C, 0xEF,
+ 0xCD, 0x3D, 0x83, 0x2F, 0xA4, 0x62, 0x93, 0x0A,
+ 0x28, 0xEF, 0xD9, 0xAD, 0x6F, 0xAE, 0x79, 0x1B,
+ 0x7E, 0xB8, 0xEC, 0x21, 0x53, 0x13, 0x21, 0xDF,
+ 0x01, 0x81, 0x4C, 0x30, 0x07, 0x58, 0x6E, 0x80,
+ 0x1A, 0xED,
+
+ 0x78, 0x66, 0x40, 0x07, 0x32, 0x18, 0x83, 0x4D,
+ 0x35, 0x65, 0x2D, 0xD2, 0x93, 0x09, 0xEF, 0xF7,
+ 0x5F, 0xD6, 0xB0, 0x99, 0xD9, 0xD0, 0xC5, 0xD7,
+ 0xF7, 0xC3, 0xDF, 0xD2, 0x01, 0xB2, 0x80, 0x7F,
+ 0xC5, 0xC8, 0x9A, 0xB3, 0x1B, 0x1D, 0x4A, 0x3E,
+ 0x05, 0xD4, 0x5B, 0xB5, 0xC5, 0x61, 0x7A, 0x16,
+ 0x49, 0x0E, 0xB3, 0x17, 0x30, 0x81, 0x10, 0xA0,
+ 0xC7, 0xE7, 0x3E, 0x1D, 0xAC, 0x2B, 0x36, 0x02,
+ 0xB2, 0x82, 0x7D, 0xAD, 0xD4, 0x24, 0x34, 0xC6,
+ 0x90, 0x19, 0x7E, 0xE0, 0xAD, 0xE2, 0xB2, 0xDE,
+ 0x59, 0xB8, 0xB5, 0x98, 0xC5, 0xEE, 0xA4, 0x14,
+ 0x8E, 0x4E, 0xEB, 0x9C, 0xA3, 0x27, 0x35, 0xF5,
+ 0x03, 0x8F, 0x3F, 0x24, 0xED, 0x7D, 0xA1, 0x86,
+ 0xFE, 0xD3, 0xD7, 0x45, 0xC8, 0x48, 0xDC, 0xA1,
+ 0x2E, 0xF9, 0xDF, 0xB3, 0x15, 0xD9, 0x16, 0x8E,
+ 0xEA, 0x52, 0xDE, 0x70, 0x71, 0xA9, 0x6A, 0x48,
+ 0x75, 0xBD, 0x6C, 0x8C, 0xF4, 0x51, 0x93, 0x35,
+ 0x7F, 0xD8, 0x59, 0xDB, 0xEE, 0x97, 0xB3, 0x15,
+ 0xC2, 0x66, 0x95, 0xB9, 0x09, 0x7F, 0x22, 0x4A,
+ 0x0D, 0xBF, 0xCE, 0x05, 0x11, 0x14, 0x72, 0x83,
+ 0x89, 0x77, 0x48,
+
+ 0x36, 0x9A, 0x46, 0xA7, 0xD8, 0x92, 0xA3, 0x4A,
+ 0xBE, 0x55, 0xDA, 0xBE, 0xB4, 0x8D, 0x58, 0x09,
+ 0x0F, 0xEB, 0x49, 0x0C, 0xFE, 0xDA, 0x5E, 0xB3,
+ 0xCF, 0xB5, 0xDF, 0x65, 0x4B, 0x37, 0xF4, 0xFF,
+ 0x0F, 0x68, 0x8C, 0xBE, 0x3C, 0x36, 0x62, 0x54,
+ 0xF1, 0xC5, 0x76, 0x64, 0x6E, 0x7F, 0xCC, 0x91,
+ 0x61, 0x77, 0xB5, 0xD1, 0x5F, 0x56, 0x35, 0xAA,
+ 0xFB, 0x72, 0x8E, 0x21, 0xFF, 0x33, 0xD5, 0x36,
+ 0xFE, 0xF6, 0x85, 0x63, 0x58, 0x02, 0x6A, 0x35,
+ 0x0C, 0x3F, 0x42, 0xE2, 0xF7, 0xE7, 0x36, 0xC1,
+ 0x11, 0x49, 0x75, 0x99, 0x6D, 0x39, 0x68, 0x7F,
+ 0x17, 0x54, 0x29, 0x5A, 0x88, 0xAF, 0x48, 0xFC,
+ 0xF7, 0xC9, 0xD1, 0x39, 0xA2, 0xBD, 0x1D, 0xBF,
+ 0xAA, 0xA2, 0x37, 0x9D, 0x71, 0x7D, 0xEC, 0xF5,
+ 0x7C, 0xEC, 0x1C, 0x21, 0xBC, 0x73, 0x4D, 0x69,
+ 0xA5, 0x0C, 0xA1, 0x6E, 0xDA, 0x84, 0x52, 0xB9,
+ 0xED, 0xE6, 0x3C, 0xAC, 0x0D, 0xEA, 0x78, 0x40,
+ 0x4A, 0x24, 0x6C, 0xC5, 0xA9, 0xB9, 0x6C, 0x9A,
+ 0x57, 0xC4, 0xA3, 0xC2, 0x66, 0x8F, 0x4D, 0x9E,
+ 0x85, 0x14, 0x26, 0xB2, 0x9B, 0xB5, 0xEF, 0x22,
+ 0xE1, 0xA1, 0x50, 0x41,
+
+ 0x96, 0x16, 0x23, 0x5B, 0x30, 0x81, 0xD1, 0x9A,
+ 0x66, 0x84, 0x92, 0xD1, 0xC4, 0x59, 0xE1, 0x24,
+ 0xFF, 0x2D, 0xA8, 0x6B, 0x83, 0x72, 0x38, 0xCD,
+ 0x7D, 0x4F, 0x5A, 0x85, 0x8A, 0x2E, 0xE9, 0x6B,
+ 0x48, 0x02, 0x54, 0xE4, 0x3B, 0x9F, 0x76, 0x13,
+ 0x9F, 0x9F, 0xF3, 0xE0, 0xF0, 0x48, 0x67, 0x9D,
+ 0x9F, 0x86, 0xCF, 0x7E, 0x7C, 0x1C, 0x0F, 0x61,
+ 0x64, 0xDA, 0x67, 0xBE, 0x68, 0x02, 0x08, 0x43,
+ 0x02, 0xF8, 0x68, 0x4C, 0x73, 0x4B, 0xCF, 0xFB,
+ 0xE8, 0xC7, 0x61, 0xCC, 0x62, 0x18, 0x39, 0xE4,
+ 0x04, 0x44, 0x36, 0x1E, 0xB7, 0xFB, 0xCC, 0x0A,
+ 0x05, 0xE7, 0x50, 0x28, 0x7F, 0xD0, 0x4F, 0xCF,
+ 0x81, 0xC2, 0x61, 0x72, 0x1C, 0x21, 0x76, 0x46,
+ 0x13, 0x05, 0x38, 0x5D, 0xEA, 0x2B, 0xF3, 0x5D,
+ 0xD9, 0x02, 0x3D, 0xBA, 0x4D, 0x79, 0x19, 0xB5,
+ 0xAC, 0xE3, 0xC7, 0x87, 0x0E, 0xA5, 0x40, 0xE5,
+ 0x68, 0x7A, 0x4A, 0xA1, 0x54, 0x1B, 0x10, 0xA0,
+ 0x9D, 0x00, 0x74, 0xB6, 0x86, 0x6D, 0x45, 0x77,
+ 0xBB, 0x7B, 0x4C, 0x8C, 0xD1, 0xCA, 0xC0, 0xA8,
+ 0xC1, 0x17, 0x17, 0x39, 0xD6, 0xC8, 0x8D, 0x75,
+ 0x63, 0x03, 0xB7, 0xCC, 0xA8,
+
+ 0x18, 0xB2, 0xD0, 0xF4, 0xB4, 0xCD, 0x4D, 0xB5,
+ 0x3F, 0x45, 0x8E, 0x05, 0x57, 0x1A, 0x9E, 0xFB,
+ 0xA7, 0x46, 0xB9, 0x97, 0xC6, 0x72, 0x46, 0x48,
+ 0x84, 0xB2, 0xB3, 0x28, 0xBC, 0xF8, 0x3A, 0x70,
+ 0x4A, 0x1A, 0x26, 0x9D, 0x71, 0x31, 0xEC, 0xB2,
+ 0xA2, 0x26, 0x8A, 0x74, 0x03, 0x7D, 0x12, 0x07,
+ 0x09, 0x7B, 0xD9, 0x89, 0x3B, 0x76, 0xD6, 0xC5,
+ 0xB9, 0x25, 0x93, 0xFD, 0x15, 0xDA, 0x26, 0x9E,
+ 0x0D, 0x74, 0xAE, 0xCE, 0x81, 0xC1, 0x3E, 0x1F,
+ 0x4C, 0x86, 0x3C, 0x99, 0x0A, 0xC5, 0x28, 0x90,
+ 0x74, 0x39, 0x03, 0x07, 0x1F, 0x6A, 0xB5, 0xF1,
+ 0x64, 0xB4, 0xEC, 0xEE, 0x04, 0xEB, 0x46, 0xCA,
+ 0xCC, 0x2B, 0x3C, 0x6A, 0x9B, 0x06, 0x0A, 0xD9,
+ 0x76, 0xB6, 0xBB, 0x8B, 0xBD, 0x57, 0x7A, 0x31,
+ 0x87, 0x1D, 0x37, 0x2B, 0xAC, 0x43, 0xA5, 0x0F,
+ 0x0F, 0xC4, 0x25, 0x17, 0x65, 0xDF, 0xD3, 0x98,
+ 0x7F, 0x31, 0x89, 0xAF, 0xE2, 0x1D, 0xED, 0x3B,
+ 0x29, 0x5F, 0x35, 0x68, 0xEC, 0xC2, 0x77, 0x4A,
+ 0x9C, 0x5A, 0xAE, 0x52, 0x13, 0x8C, 0x98, 0x47,
+ 0x03, 0x1B, 0x20, 0x1A, 0x22, 0x4D, 0x87, 0x9D,
+ 0x40, 0x86, 0x48, 0xF8, 0x60, 0xFB,
+
+ 0x63, 0x82, 0x97, 0xF6, 0x37, 0x44, 0x0E, 0x4B,
+ 0x54, 0x92, 0xA1, 0xFB, 0x06, 0x95, 0x89, 0x79,
+ 0x8F, 0x50, 0x5F, 0xD3, 0x46, 0x7A, 0xEB, 0xEC,
+ 0x98, 0x38, 0x40, 0x0E, 0xCC, 0x6C, 0x35, 0xBF,
+ 0x50, 0xD1, 0x6A, 0x3E, 0x08, 0x2E, 0x50, 0x8E,
+ 0xC2, 0xEB, 0xF3, 0xD8, 0x5A, 0xE8, 0xE3, 0xF4,
+ 0xC0, 0x37, 0x88, 0x04, 0x32, 0xAF, 0x17, 0xFC,
+ 0xEE, 0x42, 0x88, 0x84, 0xE7, 0xAD, 0x0F, 0xA7,
+ 0x51, 0xAB, 0x6A, 0xD5, 0x4B, 0xCF, 0xDB, 0xC2,
+ 0x09, 0xEF, 0x5D, 0x6B, 0x7F, 0x12, 0x79, 0x13,
+ 0xB0, 0xE8, 0xDE, 0x80, 0x72, 0x71, 0xD8, 0xDB,
+ 0x4E, 0x08, 0xF0, 0xA8, 0x7A, 0x68, 0xF8, 0x82,
+ 0xD5, 0xFD, 0xD3, 0x4A, 0x58, 0x2A, 0x99, 0x65,
+ 0xC2, 0x2C, 0x97, 0x59, 0x13, 0xA8, 0x96, 0x52,
+ 0xC3, 0xA9, 0x17, 0x47, 0xBA, 0x9C, 0xD9, 0xBB,
+ 0xBE, 0xAF, 0x91, 0x6F, 0xE0, 0xE3, 0x52, 0x9B,
+ 0xA5, 0x49, 0x7B, 0xEF, 0x5F, 0x2B, 0x03, 0xD7,
+ 0x4C, 0x46, 0xC0, 0xE8, 0x3F, 0xE5, 0x68, 0x7D,
+ 0xC9, 0xCC, 0x63, 0xA8, 0x85, 0x78, 0xFD, 0x0F,
+ 0x6A, 0x09, 0xBE, 0x1B, 0x1B, 0x62, 0x7A, 0x43,
+ 0x57, 0xF3, 0x7B, 0xC7, 0xD4, 0x9F, 0xF0,
+
+ 0x48, 0xA5, 0xCC, 0x95, 0x4E, 0xDD, 0xE7, 0xF9,
+ 0x53, 0x3C, 0x37, 0xAC, 0xAA, 0x4D, 0xD7, 0x46,
+ 0x53, 0xD8, 0xC5, 0x51, 0x27, 0xFE, 0x09, 0x24,
+ 0x56, 0x0D, 0x9D, 0x57, 0x3B, 0x07, 0xB6, 0xA1,
+ 0x0E, 0x75, 0xF3, 0xC4, 0x80, 0x06, 0x49, 0x0B,
+ 0xFB, 0x36, 0x3A, 0x98, 0xB0, 0x98, 0xB8, 0xD1,
+ 0x4A, 0x9F, 0x7A, 0x3D, 0x06, 0x32, 0xDE, 0x00,
+ 0x8C, 0xF5, 0x5C, 0x65, 0xE8, 0xCB, 0x15, 0xF7,
+ 0x77, 0xE6, 0x93, 0x1F, 0x56, 0x21, 0x48, 0x7B,
+ 0xFF, 0xD1, 0x7E, 0xA2, 0xB1, 0xDB, 0x36, 0xC1,
+ 0x3D, 0x23, 0x9F, 0x8B, 0x2B, 0x23, 0x90, 0x58,
+ 0x9A, 0x60, 0xF2, 0x8D, 0x61, 0xAD, 0x69, 0x5C,
+ 0xC4, 0xA5, 0xB3, 0x68, 0xF0, 0x98, 0xD1, 0xB2,
+ 0xEA, 0x03, 0xE7, 0x02, 0x19, 0x81, 0x26, 0x5D,
+ 0x20, 0x4E, 0x61, 0xF1, 0xEC, 0xE6, 0x6C, 0xEF,
+ 0x0E, 0x55, 0x6F, 0x6D, 0x11, 0x84, 0x1A, 0x5B,
+ 0x7E, 0x82, 0x66, 0x88, 0x44, 0x63, 0x99, 0xB1,
+ 0x5B, 0xC5, 0xFB, 0x47, 0xFF, 0x9C, 0x39, 0xD6,
+ 0xC2, 0x96, 0xEC, 0xE3, 0xA7, 0xAA, 0xF7, 0xC2,
+ 0x93, 0xB2, 0x0D, 0x7B, 0x2A, 0xF8, 0xBA, 0x22,
+ 0x2E, 0xA5, 0x7C, 0x88, 0x41, 0x7E, 0x8A, 0xFA,
+
+ 0x0F, 0x63, 0x92, 0x0D, 0x42, 0x3E, 0x56, 0x78,
+ 0x82, 0x58, 0xB7, 0x5A, 0xB4, 0xFF, 0x25, 0x5E,
+ 0xCD, 0x05, 0x8A, 0x3B, 0x00, 0xE7, 0xF0, 0x70,
+ 0xFE, 0x38, 0xC4, 0x17, 0x4D, 0x0A, 0x26, 0x71,
+ 0x3F, 0x64, 0x1F, 0x85, 0xE2, 0xF6, 0xED, 0x07,
+ 0x79, 0xDF, 0x7D, 0x03, 0x45, 0x0E, 0x26, 0xB1,
+ 0xC8, 0xD7, 0x7C, 0xE0, 0xF6, 0x3E, 0x6C, 0xDC,
+ 0xB2, 0x58, 0xFD, 0x56, 0x47, 0x69, 0xE1, 0x41,
+ 0xEB, 0x88, 0xEB, 0xE9, 0x8E, 0x73, 0x68, 0x4A,
+ 0xB4, 0xC3, 0x35, 0xA0, 0x2F, 0x8D, 0x07, 0x1E,
+ 0xE9, 0x7E, 0x63, 0x4D, 0x73, 0xEE, 0x79, 0x6A,
+ 0xA6, 0x84, 0x4A, 0x22, 0xE7, 0x88, 0xBC, 0x59,
+ 0x83, 0x41, 0xCD, 0x16, 0x73, 0x7C, 0xE3, 0xC0,
+ 0xEF, 0x23, 0x8C, 0x7A, 0x24, 0x16, 0x3F, 0x77,
+ 0x72, 0x10, 0xCF, 0x32, 0x1F, 0x2E, 0x37, 0xED,
+ 0x1B, 0x90, 0xD4, 0x4C, 0x71, 0x4D, 0x81, 0xBD,
+ 0x36, 0x6B, 0x6A, 0x2E, 0x07, 0xAD, 0x32, 0x35,
+ 0x76, 0x67, 0x66, 0xE1, 0x76, 0x95, 0x2F, 0x0A,
+ 0xF3, 0xF7, 0xC3, 0x25, 0x3D, 0xDF, 0xA1, 0x89,
+ 0xC2, 0xC1, 0x15, 0x7C, 0xD6, 0xA0, 0x07, 0x14,
+ 0x7D, 0x81, 0x83, 0x3B, 0x96, 0xBA, 0x39, 0x57,
+ 0x01,
+
+ 0x41, 0xC2, 0x86, 0x92, 0x97, 0xA5, 0x85, 0x6B,
+ 0xA6, 0xEC, 0x46, 0xB2, 0xA1, 0xF7, 0x9F, 0x4C,
+ 0x95, 0xA8, 0xEE, 0xE0, 0xB8, 0x83, 0x46, 0x6A,
+ 0xAD, 0x9C, 0xD1, 0x91, 0x42, 0xD8, 0x18, 0xC1,
+ 0xA9, 0x54, 0x1A, 0xCA, 0xA6, 0x66, 0xF7, 0xE2,
+ 0x9F, 0x82, 0x73, 0xE9, 0x17, 0x32, 0x23, 0x35,
+ 0x3E, 0x18, 0x5C, 0xAE, 0x59, 0xB7, 0x6A, 0x04,
+ 0x97, 0xD1, 0x1F, 0xB2, 0x58, 0xC9, 0x37, 0xFD,
+ 0xE0, 0xC5, 0xA4, 0x6C, 0x9A, 0x00, 0x9B, 0x4C,
+ 0x06, 0x32, 0xF4, 0xA3, 0x94, 0xBF, 0xA8, 0x49,
+ 0xFE, 0xC2, 0x45, 0xA8, 0xB5, 0x32, 0x86, 0x5F,
+ 0xBA, 0xFD, 0xD1, 0x60, 0x4D, 0xF1, 0x43, 0xE1,
+ 0x55, 0x75, 0xD8, 0xD6, 0x1F, 0xD5, 0x7F, 0x35,
+ 0x67, 0x39, 0x74, 0x9C, 0x3B, 0x50, 0xBE, 0xC0,
+ 0x67, 0xA1, 0x90, 0x0F, 0x90, 0x27, 0xAD, 0xB9,
+ 0x97, 0x0C, 0xBC, 0x2A, 0xEF, 0x4D, 0x8F, 0x69,
+ 0x08, 0x50, 0xBD, 0x69, 0xE9, 0x2B, 0xB3, 0x37,
+ 0xB5, 0x90, 0x81, 0x73, 0x63, 0x64, 0xE6, 0x6A,
+ 0xF0, 0xEF, 0xB1, 0xEC, 0x9C, 0x8B, 0x23, 0xE3,
+ 0xBA, 0xDD, 0x10, 0x1A, 0x0E, 0x6A, 0x76, 0x4C,
+ 0x58, 0xAF, 0x8C, 0x10, 0xDD, 0xFE, 0xCB, 0x82,
+ 0x53, 0x9A,
+
+ 0xB5, 0x42, 0x48, 0x28, 0x65, 0x88, 0xE8, 0xB7,
+ 0xB6, 0xCD, 0xAB, 0x9B, 0x31, 0xFE, 0xEC, 0xD7,
+ 0xBF, 0x43, 0x1B, 0x30, 0x75, 0x57, 0x96, 0x3E,
+ 0x34, 0x5C, 0xAA, 0x37, 0x83, 0x1C, 0xA3, 0x08,
+ 0x88, 0x31, 0xA0, 0x96, 0x40, 0x50, 0x7D, 0x5C,
+ 0x26, 0x66, 0x8D, 0x71, 0x95, 0xE0, 0xB8, 0x83,
+ 0x90, 0x8D, 0x9B, 0xBF, 0x85, 0x67, 0x08, 0x88,
+ 0x9F, 0x96, 0xC4, 0x31, 0xEC, 0xED, 0x6E, 0x9A,
+ 0x7E, 0x62, 0x20, 0x9A, 0xD2, 0xC6, 0xEA, 0x6B,
+ 0x65, 0xB2, 0xC5, 0xBB, 0xD3, 0x82, 0xC0, 0x0D,
+ 0xF6, 0x37, 0x3F, 0xAB, 0x88, 0xFA, 0x7E, 0xFC,
+ 0x4D, 0xE4, 0x83, 0x32, 0x8F, 0x3A, 0xFF, 0xAC,
+ 0x12, 0x81, 0xFC, 0x49, 0x0E, 0xA6, 0x37, 0xA0,
+ 0xFC, 0x40, 0x47, 0x4B, 0x14, 0x42, 0xC0, 0x0B,
+ 0xE5, 0x2D, 0x26, 0x5C, 0x2B, 0x4D, 0x0C, 0xBE,
+ 0xC1, 0x63, 0x67, 0x75, 0xB4, 0x1D, 0xB3, 0x9D,
+ 0xAA, 0xD6, 0x7C, 0xC3, 0x53, 0xD5, 0x0F, 0xE7,
+ 0x7F, 0xFA, 0xC0, 0xB5, 0x93, 0xBE, 0x18, 0x40,
+ 0x3B, 0x71, 0x32, 0xF1, 0x0F, 0x78, 0x53, 0xA1,
+ 0x01, 0xC6, 0xF6, 0x60, 0xEA, 0x50, 0x3A, 0x62,
+ 0x30, 0xBD, 0x1E, 0xE1, 0x88, 0x7C, 0x30, 0x9F,
+ 0xE4, 0x8E, 0x3F,
+
+ 0x2A, 0x34, 0xC2, 0x7C, 0xAA, 0x2B, 0xA1, 0xC0,
+ 0x1A, 0xF5, 0xA8, 0xBC, 0xB8, 0x1E, 0x17, 0x9D,
+ 0xE3, 0x4E, 0x65, 0xB4, 0x4E, 0x9A, 0xB7, 0x6C,
+ 0xDD, 0x1E, 0x86, 0xA0, 0x68, 0x4D, 0x83, 0xB7,
+ 0x06, 0xD3, 0x5E, 0xAC, 0xB0, 0x9F, 0x00, 0x00,
+ 0x62, 0xD2, 0xCD, 0x67, 0x0C, 0x2D, 0xA9, 0x25,
+ 0xC1, 0x6E, 0xA8, 0xB0, 0x0E, 0xCF, 0xD9, 0x1D,
+ 0x5D, 0x5A, 0x04, 0xD9, 0xEA, 0x3F, 0x57, 0xE1,
+ 0x25, 0x19, 0xF4, 0x9D, 0x3C, 0x7D, 0xE0, 0x65,
+ 0x98, 0xF2, 0xD1, 0x92, 0xCA, 0x8E, 0x97, 0x6B,
+ 0x61, 0x58, 0x2B, 0xB4, 0x2A, 0xB4, 0x7A, 0x2A,
+ 0xEC, 0x93, 0xC4, 0xCB, 0x54, 0x58, 0x96, 0xD1,
+ 0x9E, 0x90, 0xA2, 0x2E, 0xD8, 0x62, 0x89, 0x97,
+ 0x2B, 0x43, 0x29, 0x6C, 0xC8, 0x78, 0x5E, 0xB8,
+ 0x25, 0x9E, 0x23, 0x92, 0x6F, 0x32, 0xAF, 0x4B,
+ 0x13, 0x6E, 0x1F, 0xB5, 0x8B, 0x8F, 0x46, 0x80,
+ 0x40, 0xD6, 0x34, 0xD4, 0x0D, 0x23, 0xA6, 0x46,
+ 0x86, 0x22, 0x51, 0xCF, 0xF5, 0xB6, 0x7E, 0x0B,
+ 0xD3, 0xE8, 0xD5, 0xAE, 0x47, 0x2C, 0xD9, 0xDA,
+ 0x61, 0x81, 0x32, 0x0A, 0xAC, 0x32, 0x83, 0x0F,
+ 0x5D, 0x06, 0x15, 0x19, 0x2D, 0x4E, 0x13, 0x7A,
+ 0xEC, 0x91, 0xEC, 0xC8,
+
+ 0xB0, 0x44, 0xEA, 0xAC, 0x35, 0x51, 0x2D, 0x29,
+ 0x50, 0x73, 0x14, 0xC6, 0x5A, 0x7B, 0x9F, 0xD2,
+ 0x75, 0xE5, 0xE0, 0xE7, 0x66, 0x8A, 0xCB, 0x54,
+ 0x1D, 0xC4, 0x8A, 0x25, 0x0C, 0x7D, 0xA1, 0xA1,
+ 0xBA, 0x4E, 0x24, 0xB6, 0xD1, 0xF8, 0x8A, 0x9E,
+ 0x49, 0xD7, 0xCA, 0x7C, 0x7D, 0x83, 0xDE, 0x3E,
+ 0xED, 0x6E, 0x26, 0x34, 0x57, 0x6F, 0x00, 0x55,
+ 0xB9, 0x44, 0x54, 0x82, 0x9B, 0x9A, 0x32, 0xDA,
+ 0xBB, 0x59, 0x48, 0x80, 0x08, 0x96, 0x2D, 0x34,
+ 0x68, 0x40, 0x27, 0xB9, 0x00, 0x80, 0xC6, 0x6F,
+ 0x42, 0x72, 0x3C, 0x9B, 0xD1, 0xA0, 0x01, 0xCC,
+ 0xD2, 0x0F, 0x33, 0x00, 0x15, 0x6A, 0x65, 0x9B,
+ 0xED, 0x91, 0xDF, 0x56, 0xE2, 0x81, 0x54, 0x06,
+ 0xA0, 0xFE, 0x0E, 0xE6, 0x54, 0x16, 0xC5, 0xA6,
+ 0x89, 0x54, 0x87, 0x7E, 0x49, 0x47, 0x6C, 0x29,
+ 0x0F, 0x1C, 0x9E, 0xF7, 0x62, 0x23, 0xEB, 0x17,
+ 0xC2, 0x7B, 0x0D, 0x8B, 0xA0, 0xEF, 0xCE, 0x03,
+ 0xDE, 0x8D, 0x58, 0x0C, 0x7B, 0x6A, 0xD7, 0x66,
+ 0x52, 0x6E, 0x93, 0x0C, 0x13, 0xDF, 0x65, 0x28,
+ 0x66, 0x38, 0xA9, 0x67, 0xE9, 0x22, 0x96, 0x71,
+ 0xD2, 0xB9, 0xA3, 0xE8, 0x61, 0x49, 0x20, 0x7C,
+ 0xD5, 0x5B, 0x49, 0xCF, 0x57,
+
+ 0x4B, 0xA0, 0x49, 0xB0, 0xEE, 0xB4, 0xED, 0x67,
+ 0x08, 0x08, 0x9D, 0xBB, 0x9F, 0xD8, 0x79, 0xE8,
+ 0x42, 0x71, 0x81, 0xDA, 0x5E, 0x8D, 0x90, 0x1B,
+ 0x4C, 0x9E, 0x71, 0xCF, 0x46, 0xEB, 0xE7, 0x14,
+ 0x96, 0x98, 0xA5, 0xDB, 0xFA, 0x35, 0x99, 0x4C,
+ 0x40, 0x21, 0x5D, 0xF8, 0xB5, 0xC5, 0xAE, 0xE5,
+ 0x29, 0x68, 0x5F, 0x4A, 0xE9, 0x1D, 0x15, 0x55,
+ 0xF1, 0x4F, 0x74, 0xD4, 0x15, 0xB3, 0x7D, 0x9F,
+ 0x37, 0xC8, 0xC8, 0xAF, 0xF1, 0xF0, 0x8D, 0xC4,
+ 0xF8, 0x36, 0xF0, 0x7A, 0xB9, 0xE6, 0xB8, 0xA9,
+ 0x66, 0x10, 0xDF, 0xFE, 0x16, 0x7C, 0x8E, 0xDE,
+ 0x57, 0x0C, 0x75, 0xBF, 0x67, 0x8C, 0x39, 0x49,
+ 0xF1, 0x66, 0x1D, 0xF2, 0x0D, 0x6D, 0xBB, 0xB4,
+ 0xC3, 0xC7, 0xD7, 0xE1, 0xB3, 0xEB, 0xE2, 0x0C,
+ 0x69, 0x4E, 0xC3, 0x60, 0x5B, 0x2B, 0xD5, 0x71,
+ 0x1D, 0x33, 0xF6, 0x9D, 0xBC, 0xAE, 0x0C, 0x7E,
+ 0x3B, 0x75, 0x16, 0x73, 0x1D, 0xD5, 0xFA, 0x71,
+ 0x04, 0xA1, 0x76, 0xA8, 0xCF, 0xB2, 0xD1, 0x8D,
+ 0x00, 0x83, 0x47, 0x14, 0x28, 0x13, 0x22, 0xF6,
+ 0x2C, 0xF1, 0xCF, 0xC1, 0xB9, 0x8F, 0x18, 0x42,
+ 0x88, 0x28, 0x9B, 0x0D, 0xFF, 0xEA, 0x2D, 0xD3,
+ 0xF8, 0xC5, 0x26, 0x49, 0x67, 0xB4,
+
+ 0x5A, 0xE7, 0x15, 0x4E, 0x9B, 0xC6, 0x57, 0xBD,
+ 0x13, 0x39, 0xD7, 0xDA, 0x9A, 0xBA, 0x06, 0xDA,
+ 0x73, 0xEC, 0x64, 0xBF, 0xF4, 0x29, 0xEB, 0x4D,
+ 0x6B, 0x9A, 0xA2, 0x0F, 0x77, 0x6F, 0xBC, 0x2B,
+ 0xC5, 0x3F, 0xE8, 0xF0, 0x5A, 0x46, 0x88, 0x3C,
+ 0x4F, 0xC0, 0x44, 0xE7, 0xAC, 0x89, 0xED, 0xF6,
+ 0xF3, 0xF2, 0xE1, 0xB7, 0x24, 0x75, 0xAB, 0x72,
+ 0xC1, 0x06, 0x0E, 0x5D, 0x02, 0x5E, 0x57, 0xA6,
+ 0xA3, 0x4E, 0x4A, 0xFE, 0x46, 0xF0, 0xB4, 0xDD,
+ 0x2F, 0xAB, 0xD6, 0xED, 0x49, 0x68, 0x6B, 0xE3,
+ 0x5D, 0xFF, 0x11, 0x67, 0xA0, 0x38, 0xD1, 0xB6,
+ 0x6E, 0x98, 0x61, 0x88, 0xA5, 0x60, 0x3E, 0x74,
+ 0xFB, 0xF6, 0x47, 0x5D, 0xB4, 0xB0, 0x1F, 0xB0,
+ 0xD0, 0xE8, 0x7B, 0xB7, 0xD4, 0x7D, 0xA1, 0xAF,
+ 0xD5, 0xD8, 0x5B, 0x83, 0xDF, 0x82, 0x29, 0xA8,
+ 0xB1, 0x50, 0x2A, 0x06, 0xA6, 0xC0, 0x4C, 0xC0,
+ 0x96, 0xA4, 0xDB, 0x95, 0x61, 0x19, 0x4E, 0x1E,
+ 0xB8, 0x79, 0x45, 0x48, 0xCA, 0x22, 0xFD, 0x20,
+ 0x9E, 0x0E, 0xE1, 0xD7, 0x28, 0x00, 0x16, 0x50,
+ 0x42, 0xE4, 0x72, 0xB0, 0x61, 0x41, 0xA4, 0x93,
+ 0x9D, 0xB9, 0x0D, 0x7F, 0x2F, 0xBB, 0xD3, 0x89,
+ 0xA1, 0xBB, 0xCF, 0xE6, 0xE0, 0x09, 0x52,
+
+ 0x0B, 0x8D, 0x85, 0x02, 0x46, 0xFB, 0x2D, 0x5A,
+ 0x4A, 0xB7, 0xC1, 0x3A, 0x8C, 0x4D, 0xA0, 0xBD,
+ 0x43, 0x52, 0xE1, 0x83, 0xA5, 0x6C, 0x78, 0x10,
+ 0xC1, 0xF1, 0xDF, 0x77, 0x66, 0x2C, 0x30, 0x82,
+ 0x12, 0x06, 0xBD, 0x79, 0x0A, 0xBD, 0x80, 0x92,
+ 0xF2, 0xCF, 0xB3, 0x50, 0xF7, 0x3A, 0x80, 0xE2,
+ 0xE5, 0xB6, 0xC8, 0x65, 0xFF, 0xB9, 0x75, 0x84,
+ 0x89, 0xB3, 0x63, 0x75, 0xA8, 0xA1, 0x45, 0x3E,
+ 0x46, 0x97, 0x4A, 0x09, 0xFF, 0xAC, 0x5B, 0xF9,
+ 0x25, 0x79, 0x49, 0x70, 0xA8, 0x87, 0x95, 0x8D,
+ 0x59, 0x2F, 0x27, 0x85, 0x02, 0x78, 0x30, 0x9F,
+ 0x72, 0xDB, 0x11, 0x88, 0x85, 0x09, 0xD4, 0x4B,
+ 0x71, 0x39, 0xF4, 0x68, 0xFB, 0x40, 0x63, 0x71,
+ 0xAA, 0xFC, 0x6C, 0xE3, 0x2A, 0xF1, 0x45, 0xF4,
+ 0xE8, 0x0E, 0x8E, 0xF4, 0xA3, 0xC9, 0x37, 0xA0,
+ 0xEF, 0xDE, 0x9C, 0x92, 0x42, 0x36, 0x95, 0x30,
+ 0x0A, 0x9A, 0x06, 0xB8, 0xEB, 0x5C, 0xE2, 0x85,
+ 0x40, 0x7C, 0x2A, 0xBD, 0xC6, 0x63, 0xCE, 0xBB,
+ 0x20, 0xC0, 0x1F, 0xE1, 0x5B, 0xDD, 0xD9, 0x62,
+ 0x2D, 0x30, 0x79, 0xBB, 0x49, 0x65, 0x2A, 0x12,
+ 0x82, 0x7A, 0x8D, 0x2F, 0xFC, 0xF7, 0xB4, 0x17,
+ 0x1B, 0x69, 0x5B, 0x90, 0x6D, 0x07, 0x0D, 0x5B,
+
+ 0x99, 0x09, 0x0A, 0xFD, 0xC2, 0x22, 0x9F, 0x2B,
+ 0x4E, 0xD3, 0x2E, 0x38, 0x10, 0x2F, 0x9D, 0xD4,
+ 0x5E, 0xFC, 0x93, 0x77, 0x7B, 0x8D, 0xD3, 0xB9,
+ 0x5E, 0x1C, 0x17, 0x29, 0x4D, 0x0A, 0xA9, 0x5D,
+ 0x3E, 0xA9, 0x59, 0xD9, 0xBA, 0xF9, 0x5B, 0x21,
+ 0xF8, 0x59, 0xA8, 0xD5, 0x5C, 0x7E, 0x01, 0xDA,
+ 0xE5, 0x4F, 0x81, 0x1C, 0xD7, 0x63, 0x16, 0xA4,
+ 0x2D, 0xE6, 0xFA, 0xAA, 0x18, 0x8C, 0x87, 0xF7,
+ 0xF2, 0x7C, 0x38, 0x0C, 0x08, 0xD6, 0xA4, 0x1E,
+ 0x61, 0x19, 0xE7, 0xE9, 0x5B, 0x7C, 0x8F, 0x1A,
+ 0xB6, 0x4B, 0x7E, 0x78, 0x12, 0x22, 0xF4, 0xCA,
+ 0x59, 0xAE, 0x69, 0xC7, 0x22, 0x1D, 0xF6, 0xBB,
+ 0xFC, 0xEF, 0x70, 0x47, 0x0E, 0x5F, 0x85, 0x75,
+ 0x26, 0xA9, 0x07, 0xFA, 0x6C, 0x59, 0x67, 0x14,
+ 0x0B, 0x86, 0xCD, 0xA4, 0x84, 0xD9, 0xB1, 0xCF,
+ 0xC4, 0x26, 0x40, 0x55, 0x3E, 0xFA, 0x5F, 0x08,
+ 0x0A, 0x89, 0x56, 0x6F, 0x3A, 0xFF, 0xE4, 0x46,
+ 0x63, 0x93, 0xB9, 0xDE, 0x2C, 0x57, 0x26, 0x96,
+ 0x38, 0x03, 0x01, 0x80, 0x02, 0x44, 0xBA, 0x96,
+ 0x20, 0x7C, 0x7C, 0x76, 0x1C, 0x0C, 0x0D, 0x72,
+ 0x56, 0x28, 0xFD, 0x9F, 0xCB, 0xD5, 0xEE, 0x92,
+ 0x61, 0x5C, 0x6F, 0x0A, 0x70, 0xBA, 0xD3, 0xFB,
+ 0xD5,
+
+ 0x79, 0xFE, 0xFA, 0xEB, 0xF2, 0x35, 0xB1, 0x0C,
+ 0x46, 0x53, 0x2E, 0x26, 0xCE, 0x1A, 0x6E, 0x36,
+ 0xD0, 0xD1, 0x4C, 0x2B, 0x55, 0x02, 0x8C, 0x39,
+ 0xA4, 0xC4, 0x14, 0x9B, 0x05, 0x83, 0x80, 0x8A,
+ 0xE6, 0x05, 0x7E, 0x0A, 0xE9, 0x1A, 0xBC, 0xBD,
+ 0xAE, 0xDE, 0xCF, 0x33, 0xC4, 0xAB, 0x10, 0x66,
+ 0x52, 0x56, 0x4D, 0xEA, 0xBD, 0xE2, 0xDA, 0xC8,
+ 0x77, 0x1D, 0x26, 0x8C, 0xD5, 0x9A, 0x01, 0xFD,
+ 0xFB, 0x49, 0x89, 0xB8, 0xE1, 0xD0, 0x48, 0x49,
+ 0x44, 0x23, 0xE2, 0xEF, 0x11, 0x74, 0x67, 0x5E,
+ 0x14, 0x01, 0x15, 0xEC, 0x39, 0x9B, 0x0A, 0x69,
+ 0x7C, 0x87, 0xC2, 0xE9, 0x58, 0x05, 0xDE, 0x15,
+ 0xA2, 0x71, 0x50, 0x73, 0x12, 0x5E, 0x5B, 0x87,
+ 0x6E, 0xAE, 0xD3, 0x8F, 0x95, 0xE9, 0x77, 0xEF,
+ 0x2F, 0xD3, 0x63, 0x5B, 0x40, 0xBB, 0xDD, 0xF0,
+ 0x01, 0x08, 0x7A, 0x5C, 0x92, 0xB6, 0x37, 0xC9,
+ 0xEB, 0x84, 0x07, 0x65, 0x92, 0xFC, 0xC6, 0xB3,
+ 0x68, 0x37, 0xED, 0x62, 0xD1, 0x70, 0xD4, 0xBD,
+ 0x28, 0xD3, 0x46, 0x94, 0x63, 0xD9, 0x56, 0xBE,
+ 0x93, 0xEC, 0x8A, 0x01, 0xB5, 0xBD, 0xC6, 0x9B,
+ 0x75, 0x08, 0x06, 0x08, 0xF1, 0xFB, 0x3F, 0xB0,
+ 0x3E, 0x18, 0x35, 0xF3, 0xFA, 0x85, 0x1A, 0xA7,
+ 0x9A, 0x8E,
+
+ 0x17, 0x73, 0x8A, 0x98, 0x3B, 0x5B, 0xAD, 0x53,
+ 0x01, 0x84, 0x65, 0x88, 0xB4, 0x47, 0x4D, 0xC8,
+ 0x8C, 0x13, 0x47, 0x75, 0xB5, 0x03, 0x43, 0x64,
+ 0xE5, 0x8D, 0x56, 0xC1, 0xC0, 0x85, 0xE8, 0x25,
+ 0xE7, 0x2F, 0xC1, 0x98, 0x58, 0xE7, 0x2D, 0xD7,
+ 0x4D, 0x2B, 0xE0, 0x2D, 0x87, 0x67, 0x72, 0x7E,
+ 0xA1, 0xAE, 0xF3, 0x86, 0x88, 0xE4, 0x69, 0x23,
+ 0x30, 0x27, 0xA3, 0x48, 0xDC, 0xA0, 0x67, 0xCC,
+ 0x54, 0x31, 0xB2, 0xB7, 0x24, 0x23, 0xB9, 0x4A,
+ 0x5A, 0x07, 0x65, 0x4C, 0x2D, 0x5A, 0x9A, 0x4E,
+ 0xB4, 0xA6, 0x70, 0xFF, 0x69, 0x3E, 0xD2, 0xC9,
+ 0x55, 0x2E, 0x4F, 0xC4, 0x2F, 0x1F, 0x89, 0x98,
+ 0x76, 0x45, 0x5F, 0xBD, 0x3A, 0x8C, 0xB6, 0x55,
+ 0x93, 0xB0, 0xA7, 0x4E, 0x75, 0xBD, 0x7D, 0x25,
+ 0x08, 0x8C, 0xAD, 0x13, 0x33, 0x24, 0x57, 0xA9,
+ 0x1C, 0x44, 0x71, 0x86, 0x7E, 0xC4, 0xC4, 0x1C,
+ 0x5B, 0x1E, 0x83, 0x37, 0x1B, 0x37, 0x98, 0x9A,
+ 0xB4, 0xDC, 0xA1, 0xC2, 0x1A, 0x69, 0x89, 0xE1,
+ 0xD9, 0x67, 0x41, 0x58, 0x72, 0x6A, 0xF8, 0x22,
+ 0x69, 0xEA, 0x53, 0xF5, 0x3C, 0x5E, 0x53, 0x5D,
+ 0x98, 0x9A, 0x2A, 0xDA, 0xF6, 0x30, 0xA0, 0xBA,
+ 0xCE, 0xF8, 0xB7, 0x4D, 0xE2, 0xBF, 0x05, 0xAA,
+ 0xF7, 0x44, 0x84,
+
+ 0x97, 0xDD, 0xB6, 0xB9, 0xD3, 0xA3, 0x8A, 0x20,
+ 0x05, 0x15, 0xD1, 0x14, 0x69, 0x33, 0x98, 0xFF,
+ 0x77, 0xDA, 0x47, 0x11, 0xC3, 0x59, 0x19, 0xFB,
+ 0x86, 0xEE, 0x3A, 0xB9, 0x4F, 0x61, 0x07, 0x6C,
+ 0x7B, 0x01, 0x89, 0x87, 0x1E, 0xA0, 0xBB, 0x34,
+ 0x60, 0x89, 0xAA, 0xE9, 0xE5, 0x03, 0xE4, 0xF7,
+ 0xA7, 0x16, 0xD0, 0xA9, 0x08, 0x3F, 0xA1, 0x25,
+ 0x57, 0xB4, 0xAD, 0x52, 0x80, 0x53, 0xB3, 0x3B,
+ 0x58, 0x58, 0x96, 0x37, 0x25, 0xEB, 0x08, 0xD9,
+ 0x63, 0xFA, 0x1F, 0xC8, 0x92, 0xF0, 0x50, 0x0D,
+ 0xAE, 0xFB, 0x16, 0x2E, 0xA7, 0xB1, 0x1E, 0x71,
+ 0x46, 0xCE, 0xE6, 0xA9, 0x4B, 0x67, 0xAC, 0xD8,
+ 0xC7, 0x01, 0x18, 0xA0, 0x83, 0xD5, 0xBA, 0xA9,
+ 0x94, 0xCD, 0x2C, 0x8C, 0x90, 0x86, 0xE9, 0x80,
+ 0x3E, 0x94, 0x0B, 0x0C, 0xDD, 0xF0, 0xB8, 0xFE,
+ 0x29, 0x9D, 0x9F, 0xAB, 0x16, 0xE6, 0x08, 0x12,
+ 0x67, 0x29, 0x45, 0x57, 0x4D, 0xB9, 0x08, 0xF3,
+ 0x44, 0x4E, 0x5C, 0x9C, 0x92, 0x69, 0xF6, 0x41,
+ 0x90, 0x17, 0x92, 0xF5, 0x1B, 0x8B, 0xBB, 0x89,
+ 0x2E, 0x3A, 0x7F, 0xAF, 0x82, 0x59, 0xA4, 0x94,
+ 0x53, 0x40, 0xF5, 0x6A, 0x2A, 0xF5, 0xA8, 0x4F,
+ 0x48, 0x2D, 0x01, 0x61, 0x6A, 0x98, 0xFD, 0xF8,
+ 0xBC, 0x46, 0xFC, 0x6F,
+
+ 0x2F, 0x20, 0x5D, 0x1C, 0xAC, 0x77, 0x49, 0x4E,
+ 0x6A, 0x21, 0x43, 0x6D, 0x67, 0x9C, 0xF6, 0x87,
+ 0xC9, 0xAF, 0x8B, 0x58, 0xF0, 0xCB, 0x8B, 0x9C,
+ 0x41, 0x7D, 0x77, 0x66, 0xFF, 0x9D, 0x6D, 0xA5,
+ 0x23, 0xAC, 0x7E, 0x35, 0x18, 0xC1, 0x8E, 0x96,
+ 0x5F, 0x9B, 0xD8, 0xDF, 0xEA, 0xA1, 0x1A, 0x4E,
+ 0xE5, 0x43, 0x6E, 0x05, 0xE7, 0xBF, 0x0B, 0x81,
+ 0xD5, 0x73, 0x6C, 0x37, 0x43, 0x82, 0xF4, 0x40,
+ 0x8F, 0x6E, 0xA2, 0x7B, 0xEC, 0x28, 0x7B, 0xD5,
+ 0xA1, 0xCB, 0x38, 0xF1, 0x62, 0x5F, 0xCC, 0xCF,
+ 0xB5, 0x87, 0x38, 0x03, 0x5D, 0x1E, 0xC9, 0x01,
+ 0x4C, 0xE1, 0x97, 0xD7, 0xC5, 0x92, 0xE2, 0xEB,
+ 0x5B, 0x49, 0xC3, 0xB9, 0xB9, 0x9D, 0x16, 0x8D,
+ 0x54, 0x57, 0xB7, 0x08, 0xA9, 0xF2, 0x1E, 0x2B,
+ 0x6B, 0x8C, 0x0C, 0x1E, 0xD6, 0x8D, 0x0E, 0xA6,
+ 0x51, 0xB5, 0xC7, 0x02, 0xC1, 0x34, 0x92, 0x95,
+ 0x8A, 0xEA, 0xF3, 0xCD, 0x37, 0x54, 0x09, 0x74,
+ 0x47, 0x04, 0x93, 0x73, 0xD9, 0x91, 0x31, 0x33,
+ 0x91, 0x4E, 0xF5, 0x08, 0x0A, 0x8A, 0x50, 0x15,
+ 0x9F, 0x08, 0x36, 0xC5, 0x74, 0xEF, 0x2B, 0xD2,
+ 0x1E, 0x05, 0xD1, 0xB7, 0x2E, 0x57, 0x3B, 0x25,
+ 0x0F, 0x91, 0x65, 0x48, 0xEB, 0x2F, 0xF3, 0xDB,
+ 0xF8, 0xE2, 0x7B, 0xAF, 0x93,
+
+ 0xB0, 0xC5, 0x54, 0xAD, 0x36, 0x9B, 0x5C, 0x03,
+ 0x86, 0x9C, 0x35, 0x73, 0xD5, 0xF9, 0x0F, 0x5F,
+ 0xEF, 0x3A, 0xFF, 0x73, 0x9E, 0xC4, 0xDB, 0x64,
+ 0x4F, 0x3E, 0xEF, 0xD2, 0x32, 0x5A, 0x7F, 0xA5,
+ 0xBF, 0x2C, 0x81, 0x00, 0xBB, 0xFA, 0x5F, 0x98,
+ 0x86, 0x71, 0x26, 0x39, 0x8F, 0xB7, 0x84, 0x38,
+ 0x9D, 0xE4, 0xF7, 0x99, 0x21, 0xB9, 0x0D, 0xF7,
+ 0x6F, 0x7F, 0xB8, 0x68, 0x8F, 0x7E, 0x7E, 0x4F,
+ 0xA7, 0x15, 0x2A, 0x82, 0xFC, 0x60, 0xCF, 0x70,
+ 0xE9, 0x86, 0xBD, 0x24, 0xA1, 0xBA, 0x30, 0xB2,
+ 0x70, 0x66, 0xBC, 0x6F, 0x1C, 0x39, 0x94, 0xB5,
+ 0x81, 0x3C, 0x54, 0x98, 0x3C, 0x82, 0xE3, 0xF8,
+ 0x6D, 0x3C, 0x1B, 0x5A, 0x7A, 0x81, 0x7A, 0x29,
+ 0xEF, 0x48, 0x3B, 0x35, 0x3F, 0x73, 0xF0, 0x05,
+ 0x12, 0xB6, 0xC9, 0x2D, 0xDA, 0xCB, 0x81, 0xBD,
+ 0xEE, 0x8F, 0x8E, 0xE7, 0x06, 0x8D, 0xD2, 0x76,
+ 0x39, 0x60, 0xF2, 0x57, 0xD6, 0xE5, 0xFC, 0x81,
+ 0x14, 0x49, 0xB4, 0x6B, 0x06, 0x6E, 0x33, 0xDC,
+ 0x2C, 0x2F, 0x4E, 0x15, 0xC8, 0xC2, 0x41, 0x95,
+ 0xA8, 0x65, 0x59, 0xCA, 0x97, 0xD8, 0xA0, 0x4A,
+ 0x1F, 0xCA, 0x35, 0xC5, 0x21, 0xBD, 0x51, 0x29,
+ 0x2B, 0x0A, 0x1B, 0x37, 0x4C, 0xF7, 0xAA, 0x88,
+ 0xDF, 0x44, 0x88, 0x05, 0x2F, 0x4B,
+
+ 0x50, 0xDC, 0xA7, 0x8B, 0xED, 0x47, 0x10, 0x06,
+ 0x63, 0xCB, 0x7D, 0x5B, 0xE6, 0xB0, 0xED, 0x90,
+ 0x55, 0xF0, 0x38, 0x3C, 0x80, 0x34, 0x2B, 0x62,
+ 0x92, 0xC5, 0x61, 0x0D, 0xEC, 0x0E, 0xD3, 0xEA,
+ 0xD6, 0x81, 0xB8, 0x4D, 0xC6, 0x3E, 0xC5, 0x19,
+ 0x70, 0x31, 0x0F, 0x2C, 0x65, 0x07, 0x0F, 0x43,
+ 0x2F, 0xA0, 0x63, 0xD7, 0xFB, 0x9B, 0xD1, 0xA9,
+ 0x60, 0x3C, 0xFE, 0x4E, 0x09, 0xAF, 0xC7, 0x04,
+ 0x4A, 0xE6, 0x75, 0x18, 0xF6, 0x53, 0x87, 0x91,
+ 0xD6, 0x33, 0x15, 0x9C, 0x32, 0xA0, 0x52, 0x82,
+ 0xC7, 0xF9, 0x17, 0x9C, 0x58, 0x2C, 0xBC, 0x75,
+ 0x88, 0x1B, 0x7D, 0x71, 0xC3, 0xCC, 0xFE, 0x60,
+ 0x08, 0xDD, 0xB0, 0x5F, 0x45, 0x49, 0x08, 0x91,
+ 0xF6, 0x42, 0x97, 0x85, 0xBB, 0xF7, 0x04, 0xAB,
+ 0xFF, 0xB6, 0xB6, 0x37, 0xA3, 0xA8, 0x1D, 0x41,
+ 0x52, 0x9F, 0x47, 0xC2, 0xD4, 0xE1, 0x32, 0x22,
+ 0x26, 0xF5, 0x26, 0x0A, 0x03, 0xD5, 0xDD, 0x37,
+ 0x95, 0xBB, 0xC0, 0xEF, 0x4C, 0x61, 0xC9, 0x87,
+ 0x43, 0x88, 0x22, 0xE9, 0x5F, 0x30, 0x0A, 0x64,
+ 0x73, 0xF3, 0x2F, 0xD2, 0x4D, 0xE8, 0x91, 0x1C,
+ 0x68, 0xBE, 0x35, 0xC3, 0xF4, 0xC4, 0xD3, 0xD2,
+ 0x01, 0xB2, 0x19, 0x28, 0x30, 0x86, 0xD9, 0xFC,
+ 0x16, 0x4A, 0x0E, 0xCC, 0xCA, 0xD6, 0xF6,
+
+ 0x74, 0xAF, 0x14, 0xA0, 0x6E, 0x50, 0x25, 0x74,
+ 0x8F, 0xC7, 0x16, 0x03, 0x56, 0x10, 0x01, 0x76,
+ 0x5B, 0x63, 0xD0, 0xEF, 0x4E, 0xA7, 0x59, 0x27,
+ 0x43, 0x0C, 0x3F, 0x8C, 0xFD, 0xB6, 0x09, 0x17,
+ 0x81, 0xD7, 0xEC, 0x94, 0x50, 0x4B, 0xC8, 0x22,
+ 0x3F, 0x82, 0x11, 0xA1, 0x58, 0x8C, 0x23, 0xBB,
+ 0x8B, 0xFB, 0x4F, 0x34, 0x31, 0x98, 0x63, 0x1B,
+ 0xC4, 0x8E, 0xCF, 0x12, 0x57, 0x68, 0x14, 0x2B,
+ 0x23, 0xA9, 0x9D, 0x17, 0x84, 0x2A, 0x53, 0xE7,
+ 0x67, 0x5A, 0xC1, 0x6E, 0x65, 0x25, 0x70, 0x25,
+ 0x76, 0x70, 0x30, 0x24, 0x85, 0xF8, 0x1F, 0x9D,
+ 0xFD, 0x8D, 0x84, 0xAD, 0x33, 0x07, 0xFD, 0x21,
+ 0x01, 0x13, 0xC0, 0x14, 0x20, 0xF2, 0xDC, 0x81,
+ 0x21, 0xEF, 0x3A, 0xCB, 0x32, 0x23, 0xB2, 0x76,
+ 0x3B, 0xA4, 0x30, 0xB6, 0x8F, 0x90, 0xE3, 0x20,
+ 0x4C, 0x81, 0x6A, 0xF4, 0x2C, 0xC3, 0x4C, 0x86,
+ 0x08, 0x86, 0x1E, 0x31, 0x48, 0x55, 0x7E, 0xF2,
+ 0xA7, 0xF5, 0xC6, 0x22, 0x19, 0x87, 0xE5, 0x6E,
+ 0xA6, 0xC5, 0x31, 0xF6, 0x1D, 0xA4, 0xD8, 0x75,
+ 0x90, 0x1C, 0x57, 0x01, 0xF5, 0xE8, 0x53, 0x3E,
+ 0x0A, 0x16, 0xDD, 0x40, 0x58, 0x0C, 0xE0, 0x8F,
+ 0xBF, 0x57, 0xFA, 0x1D, 0x37, 0x15, 0xC6, 0x63,
+ 0xC1, 0x57, 0x0C, 0x6D, 0x83, 0x6C, 0xA4, 0x0E,
+
+ 0x6A, 0x33, 0x55, 0x52, 0x04, 0x3E, 0x41, 0x83,
+ 0x22, 0xED, 0x2A, 0xAC, 0x33, 0xEF, 0xA6, 0xA9,
+ 0x8E, 0x21, 0x9D, 0x2B, 0xFB, 0x20, 0x80, 0x22,
+ 0x0F, 0x7A, 0xB4, 0x67, 0xFF, 0x76, 0xFA, 0x1D,
+ 0x1B, 0x26, 0xF9, 0xD4, 0x3A, 0x66, 0x99, 0x4C,
+ 0xFD, 0x45, 0x61, 0x96, 0x02, 0x3F, 0xD3, 0x13,
+ 0xE4, 0x44, 0x30, 0x30, 0x6B, 0x76, 0x77, 0xEA,
+ 0x66, 0x69, 0x1B, 0x82, 0xE6, 0xA2, 0x50, 0x69,
+ 0xFD, 0x5D, 0xAD, 0x59, 0x82, 0x94, 0xA1, 0xF3,
+ 0x78, 0x5B, 0x00, 0x7B, 0x6E, 0xE9, 0xA2, 0xB9,
+ 0xB4, 0x56, 0xF9, 0xD5, 0x5C, 0x42, 0x89, 0xA5,
+ 0x7E, 0x86, 0xFE, 0x61, 0x6C, 0xF1, 0x0A, 0xFC,
+ 0xC9, 0x7D, 0x9C, 0xF0, 0xE7, 0x7F, 0xFE, 0xCD,
+ 0x85, 0xEC, 0x68, 0x68, 0xC5, 0x6F, 0x06, 0x35,
+ 0x4B, 0xA6, 0x15, 0xF8, 0x38, 0xF5, 0x1B, 0x56,
+ 0x20, 0x75, 0xCE, 0xA4, 0xCB, 0x5F, 0x60, 0x96,
+ 0xE7, 0xEF, 0x71, 0x1B, 0x1D, 0xF5, 0xD1, 0x96,
+ 0xA1, 0x9C, 0x64, 0xFA, 0x2F, 0x88, 0x9C, 0x87,
+ 0x53, 0xC5, 0x08, 0xE5, 0x93, 0xD0, 0x6E, 0xDB,
+ 0xA1, 0x84, 0x1C, 0x49, 0x79, 0x38, 0x48, 0xDD,
+ 0x6B, 0xD0, 0x80, 0x52, 0x51, 0x4A, 0x96, 0x9C,
+ 0x4A, 0x48, 0xB3, 0x9B, 0x86, 0x2F, 0xDC, 0x32,
+ 0x34, 0x27, 0x04, 0xAB, 0x37, 0xB2, 0x50, 0x6C,
+ 0xB8,
+
+ 0x86, 0x42, 0xAF, 0x92, 0x97, 0x70, 0x4B, 0x6A,
+ 0xC3, 0x85, 0x01, 0xE0, 0xFE, 0x10, 0x0A, 0x58,
+ 0xD8, 0xF8, 0x1F, 0x0C, 0xA0, 0xF3, 0x41, 0x40,
+ 0x1F, 0x90, 0x54, 0x07, 0x52, 0x34, 0x2C, 0xC8,
+ 0x20, 0x3A, 0xA5, 0x1D, 0x12, 0x59, 0xC5, 0xCA,
+ 0x3F, 0x60, 0x7E, 0x9F, 0xB0, 0xB3, 0x66, 0x99,
+ 0x67, 0xD6, 0x0B, 0x05, 0x54, 0xB5, 0xE3, 0x7E,
+ 0xC6, 0x97, 0xF3, 0xD5, 0xC0, 0x73, 0xE9, 0xE2,
+ 0x70, 0x20, 0x78, 0x15, 0x74, 0x2F, 0x19, 0xCC,
+ 0x0F, 0xA9, 0xCC, 0xE1, 0xAE, 0x60, 0x6A, 0x05,
+ 0x97, 0xE4, 0x5A, 0x6F, 0xF9, 0xB6, 0x40, 0x31,
+ 0xE1, 0x41, 0xF2, 0x72, 0x3E, 0xB2, 0xEB, 0x78,
+ 0x33, 0x7E, 0x0A, 0xB4, 0x39, 0xE3, 0xEE, 0x99,
+ 0x17, 0x6C, 0x2F, 0x2F, 0xA8, 0x3C, 0x2C, 0xFC,
+ 0x70, 0x53, 0x53, 0x14, 0x82, 0x62, 0xCA, 0x55,
+ 0x23, 0x20, 0xFF, 0x7F, 0xC5, 0xE9, 0x28, 0xB9,
+ 0xA2, 0x15, 0x82, 0x6B, 0xED, 0x1C, 0xBB, 0xD6,
+ 0x74, 0x8E, 0xE5, 0x2F, 0x54, 0x97, 0x05, 0xAB,
+ 0x88, 0xF8, 0x6E, 0x5E, 0x45, 0x52, 0x61, 0x3B,
+ 0xCD, 0x9F, 0x3E, 0xE0, 0x43, 0x30, 0x37, 0x73,
+ 0x50, 0xE3, 0x21, 0x29, 0xAA, 0x48, 0x7B, 0xDE,
+ 0x50, 0x2B, 0xBC, 0x34, 0xBF, 0xB3, 0x0F, 0xF7,
+ 0xCB, 0x78, 0x4B, 0xDE, 0x7B, 0x1D, 0xAC, 0xFC,
+ 0xEB, 0x03,
+
+ 0x76, 0xD3, 0x4B, 0xE8, 0x19, 0x32, 0xEE, 0xA7,
+ 0xD5, 0x21, 0xE4, 0xFF, 0x60, 0x32, 0xED, 0xE4,
+ 0x6D, 0xC3, 0xE2, 0xA4, 0xD2, 0xEC, 0x0B, 0x41,
+ 0x8E, 0xF2, 0xE3, 0x83, 0x84, 0x18, 0xE5, 0xF4,
+ 0xBA, 0xE7, 0x17, 0xED, 0xF7, 0xF6, 0xC8, 0x6C,
+ 0xA9, 0xC7, 0xF7, 0x23, 0x9E, 0x0F, 0xEC, 0x4C,
+ 0x51, 0x20, 0xB8, 0xEF, 0x02, 0xCC, 0xFF, 0xBB,
+ 0xDE, 0x1C, 0x47, 0x8A, 0xAB, 0x2D, 0xDF, 0xF6,
+ 0x86, 0x0B, 0xC8, 0xFB, 0xDE, 0x24, 0x64, 0x1F,
+ 0x99, 0x4F, 0x44, 0xC9, 0x78, 0x45, 0xD2, 0x2A,
+ 0x7A, 0x3B, 0x1C, 0xC5, 0xD8, 0x87, 0x29, 0xEB,
+ 0x5E, 0x02, 0x12, 0x93, 0xF7, 0xED, 0x21, 0xFF,
+ 0x50, 0xDB, 0xD9, 0xD4, 0x0B, 0x1C, 0xC9, 0x1D,
+ 0xF2, 0x1F, 0x9C, 0x93, 0x2F, 0xDA, 0x90, 0xB0,
+ 0xF9, 0x25, 0x4F, 0x25, 0xE7, 0x64, 0xB4, 0xD6,
+ 0x78, 0xB3, 0x68, 0xD8, 0x46, 0xCF, 0xE4, 0xC7,
+ 0x15, 0x28, 0xC2, 0x34, 0x6E, 0xB2, 0x4F, 0x12,
+ 0xD2, 0x89, 0xDE, 0x77, 0xDA, 0x58, 0x40, 0x62,
+ 0x8B, 0x55, 0xF7, 0x80, 0x82, 0x3C, 0xC3, 0xAC,
+ 0x7C, 0xF4, 0x2E, 0xDD, 0xC4, 0x70, 0x52, 0x63,
+ 0x17, 0x7F, 0x44, 0xF7, 0x65, 0x59, 0x3D, 0x91,
+ 0x95, 0x18, 0xB0, 0xA4, 0xA0, 0xAF, 0x52, 0x3A,
+ 0xD3, 0xC0, 0xDD, 0x0C, 0x00, 0xC1, 0xD7, 0xA6,
+ 0x1D, 0x5E, 0x35,
+
+ 0xC5, 0x4F, 0x57, 0x22, 0xF0, 0xE2, 0x42, 0xEE,
+ 0x03, 0x5C, 0xDE, 0x88, 0x0A, 0x6E, 0xEB, 0xA4,
+ 0x41, 0xEF, 0x55, 0x9D, 0x37, 0x21, 0xAE, 0x2A,
+ 0xA9, 0x9D, 0x92, 0xDC, 0xCF, 0x5F, 0xD3, 0x28,
+ 0x23, 0x5D, 0x22, 0xDB, 0x89, 0x31, 0x4D, 0x60,
+ 0x08, 0x92, 0x78, 0x3A, 0x5D, 0xAE, 0x91, 0x1A,
+ 0x93, 0xCD, 0x4D, 0x62, 0x40, 0xA2, 0x18, 0x1A,
+ 0x6B, 0xCE, 0x34, 0x0D, 0x3B, 0x09, 0xC6, 0xE6,
+ 0x3F, 0x1B, 0x88, 0x19, 0x14, 0x29, 0xAD, 0x75,
+ 0x06, 0x1B, 0xD9, 0xE2, 0xEC, 0xE7, 0x1B, 0xC9,
+ 0x7A, 0xD3, 0x18, 0x86, 0xE7, 0x36, 0xAD, 0x21,
+ 0x7D, 0xA2, 0xDC, 0x1C, 0x97, 0xBA, 0xB2, 0xCB,
+ 0x59, 0x19, 0x7D, 0x20, 0xC5, 0x68, 0xB8, 0xBD,
+ 0x51, 0x49, 0x5B, 0x45, 0xAB, 0x47, 0x33, 0x63,
+ 0xA2, 0xEC, 0x4C, 0x2D, 0x69, 0x91, 0x27, 0x86,
+ 0x72, 0x28, 0xDB, 0x96, 0x55, 0x5D, 0x1A, 0x2F,
+ 0x7E, 0x5D, 0xC6, 0x0A, 0x69, 0xAB, 0x8C, 0x8B,
+ 0x36, 0x87, 0xB4, 0x1A, 0x15, 0xE4, 0x68, 0x21,
+ 0xDB, 0x65, 0x87, 0xBA, 0x24, 0xBD, 0x1F, 0xFA,
+ 0x5C, 0x4B, 0x48, 0x21, 0x83, 0xD8, 0x04, 0x50,
+ 0x31, 0x83, 0xF7, 0x21, 0xC5, 0xA8, 0xA9, 0x8A,
+ 0x5E, 0xC6, 0x1C, 0x40, 0x8E, 0x29, 0xB3, 0xF2,
+ 0xA8, 0x86, 0xED, 0x60, 0xCA, 0xF8, 0x24, 0x7F,
+ 0x09, 0xAE, 0x36, 0x3F,
+
+ 0x6D, 0x99, 0x39, 0x36, 0xA1, 0x3E, 0x29, 0x65,
+ 0x55, 0xA1, 0x90, 0x10, 0xB5, 0x49, 0x64, 0xE3,
+ 0x09, 0xB2, 0xDB, 0x65, 0xF1, 0x5E, 0x05, 0x1E,
+ 0x0E, 0x6A, 0x8C, 0x38, 0xDF, 0xE1, 0xB8, 0x87,
+ 0x15, 0x2C, 0xCB, 0x4D, 0xD7, 0x44, 0xDB, 0x3B,
+ 0x80, 0xA2, 0xEA, 0x9A, 0x7A, 0xA8, 0x39, 0xE2,
+ 0x33, 0xFC, 0x40, 0xCD, 0x92, 0xB8, 0x62, 0x1D,
+ 0x9E, 0xC7, 0x65, 0x65, 0x3C, 0x24, 0x6A, 0x77,
+ 0x11, 0xA5, 0xEE, 0x86, 0x19, 0x5E, 0xCF, 0x01,
+ 0xF7, 0x74, 0x64, 0xAA, 0xDF, 0xD3, 0x0B, 0x54,
+ 0xF8, 0xEB, 0x9F, 0xE5, 0x3B, 0x9B, 0x3A, 0xCB,
+ 0x36, 0x65, 0xA6, 0xD3, 0x8B, 0x5D, 0xD3, 0x55,
+ 0xC4, 0xD6, 0x26, 0x46, 0x5D, 0x66, 0x4E, 0xEB,
+ 0x7F, 0xB3, 0x1F, 0x36, 0x12, 0x92, 0x50, 0xF4,
+ 0xE3, 0x2B, 0x90, 0x32, 0xFF, 0x56, 0x90, 0x81,
+ 0xC3, 0x52, 0x7A, 0x26, 0x67, 0xA5, 0x4E, 0xC1,
+ 0x3B, 0xB9, 0x44, 0x4B, 0x6F, 0x96, 0xD7, 0xD4,
+ 0xE9, 0x67, 0x10, 0x36, 0xD8, 0xAB, 0xC3, 0x0C,
+ 0x17, 0xCF, 0xC1, 0x38, 0xC9, 0xD6, 0x7B, 0xB9,
+ 0xFC, 0xF9, 0x1D, 0x49, 0x87, 0x84, 0xCF, 0x86,
+ 0x72, 0xFD, 0x95, 0x15, 0xBF, 0x27, 0x1F, 0xAB,
+ 0x64, 0x81, 0xCF, 0x99, 0x96, 0x2E, 0x15, 0x57,
+ 0xA5, 0xD7, 0x7D, 0x0E, 0xB9, 0xDC, 0x6A, 0x44,
+ 0xFC, 0x80, 0x80, 0x66, 0x2E,
+
+ 0x9C, 0x95, 0xB5, 0x62, 0xE3, 0x90, 0x98, 0xF3,
+ 0x02, 0x26, 0x65, 0x18, 0x99, 0x4B, 0xCC, 0x67,
+ 0x42, 0xCF, 0x7B, 0x21, 0xC4, 0xB7, 0x97, 0x99,
+ 0x50, 0xBD, 0x05, 0x49, 0xB4, 0xA3, 0x9E, 0xCA,
+ 0x85, 0xD1, 0xD0, 0x65, 0xF3, 0x69, 0x8E, 0x21,
+ 0x49, 0xCA, 0x23, 0x89, 0x8F, 0x9A, 0x03, 0x7B,
+ 0xB0, 0x55, 0xE4, 0x21, 0x7D, 0x00, 0xC1, 0xFA,
+ 0xBC, 0x24, 0x65, 0x5C, 0x83, 0x67, 0x5B, 0x97,
+ 0x01, 0xCB, 0x00, 0x82, 0xF2, 0xA1, 0x3E, 0xE8,
+ 0xCC, 0xCE, 0x00, 0x5A, 0x79, 0xB5, 0xF7, 0x13,
+ 0xD8, 0x9D, 0x57, 0x8F, 0x98, 0x49, 0x80, 0x72,
+ 0xC4, 0xA5, 0x7C, 0x03, 0x91, 0x77, 0x1F, 0x82,
+ 0x07, 0x42, 0x88, 0x36, 0x00, 0x9B, 0x09, 0x87,
+ 0x90, 0xE6, 0x6C, 0x53, 0xF6, 0x3A, 0x5F, 0x6E,
+ 0x71, 0xA3, 0xDB, 0x58, 0x49, 0x69, 0xCC, 0x9B,
+ 0x69, 0x85, 0x43, 0xFF, 0x1E, 0xEA, 0x53, 0x3C,
+ 0xF5, 0xD9, 0x7C, 0x63, 0xF6, 0x85, 0xEB, 0xE0,
+ 0xE9, 0x20, 0x6F, 0xB1, 0x5F, 0xFE, 0xEA, 0xF1,
+ 0x30, 0x1F, 0x7E, 0x61, 0x10, 0x74, 0x29, 0x06,
+ 0xB4, 0x9F, 0xAC, 0xA5, 0x3E, 0xC1, 0xAF, 0xF8,
+ 0x6A, 0x3F, 0x7E, 0xDE, 0x75, 0x67, 0xB7, 0x79,
+ 0xAB, 0x96, 0x82, 0xD9, 0x52, 0x08, 0xC9, 0xEA,
+ 0x1F, 0x69, 0xBF, 0xF6, 0xEA, 0xE2, 0x6F, 0x7B,
+ 0xB7, 0x2F, 0xED, 0xA8, 0x50, 0xD4,
+
+ 0x5E, 0xAA, 0x52, 0xBD, 0xD4, 0x77, 0xAF, 0x8B,
+ 0x18, 0x01, 0xE0, 0xF7, 0xC4, 0xE7, 0x4B, 0x86,
+ 0xAB, 0x7D, 0x11, 0xE6, 0x70, 0x98, 0x34, 0x7C,
+ 0x53, 0x63, 0x75, 0xFE, 0xE8, 0xB4, 0x7A, 0x95,
+ 0x59, 0x0A, 0x4D, 0x78, 0x65, 0x7E, 0x93, 0xEE,
+ 0xD0, 0x84, 0x3D, 0xE0, 0xB6, 0xA2, 0x2D, 0x8A,
+ 0x36, 0x68, 0x04, 0xB4, 0x84, 0x38, 0x14, 0x1E,
+ 0x7A, 0x61, 0x6B, 0x60, 0xA0, 0x4A, 0xE1, 0x7D,
+ 0x4B, 0xB8, 0x8F, 0x31, 0x49, 0x66, 0xE2, 0x3E,
+ 0x73, 0xE5, 0xE1, 0x73, 0xB9, 0x9A, 0x4D, 0xAD,
+ 0xD5, 0xED, 0x42, 0x53, 0x41, 0x42, 0x21, 0x2E,
+ 0xC3, 0x36, 0x8B, 0x0A, 0x40, 0xB5, 0xB4, 0x0C,
+ 0xB3, 0xF0, 0x53, 0x34, 0xD7, 0xE5, 0xE0, 0x70,
+ 0xB1, 0xEA, 0x86, 0x5E, 0x9A, 0x39, 0x30, 0x95,
+ 0x84, 0xC7, 0x57, 0x93, 0xC9, 0x7A, 0xF6, 0x10,
+ 0x3D, 0x3F, 0x68, 0x33, 0xC3, 0x4F, 0x45, 0x36,
+ 0xB0, 0xA4, 0xDF, 0x58, 0xE8, 0xB7, 0x4A, 0x42,
+ 0x8C, 0x6D, 0x04, 0xCF, 0x24, 0xA5, 0x69, 0x95,
+ 0xDE, 0x04, 0xC3, 0xA8, 0xDD, 0xE3, 0x78, 0x44,
+ 0xA0, 0x9F, 0x11, 0x9B, 0xB4, 0xA2, 0x27, 0x7A,
+ 0x15, 0xA3, 0x9D, 0x27, 0x80, 0x35, 0xB4, 0x9F,
+ 0x33, 0xBE, 0x27, 0x3A, 0xE1, 0x1F, 0x67, 0x97,
+ 0x1D, 0x1A, 0x7D, 0x11, 0x59, 0xEF, 0x01, 0x5E,
+ 0x8E, 0xD9, 0xA8, 0x16, 0x94, 0x54, 0xD9,
+
+ 0x49, 0x52, 0x78, 0x3A, 0x42, 0x33, 0x66, 0xEF,
+ 0x71, 0xB1, 0xF3, 0x8B, 0x98, 0xB2, 0x65, 0x8A,
+ 0x8A, 0x5D, 0xE8, 0x6B, 0x9B, 0xFB, 0xEF, 0x15,
+ 0x86, 0x3C, 0x68, 0x1D, 0x3A, 0x5C, 0xA7, 0xD8,
+ 0x3B, 0x33, 0x95, 0xF0, 0x9C, 0xB8, 0xA6, 0x92,
+ 0x11, 0x79, 0xB2, 0xD9, 0x3C, 0x18, 0x7F, 0xBB,
+ 0xF9, 0xAA, 0x43, 0x01, 0xD1, 0x7D, 0xC7, 0xB7,
+ 0x0D, 0x49, 0x44, 0x0D, 0x36, 0x0B, 0xD9, 0xC6,
+ 0x54, 0x79, 0x0A, 0x63, 0x79, 0x86, 0xBD, 0x0B,
+ 0xC4, 0x03, 0xF5, 0xFC, 0x1E, 0x37, 0xE5, 0x24,
+ 0x30, 0x5A, 0x35, 0x1D, 0x13, 0xE8, 0x35, 0x9E,
+ 0x42, 0x0F, 0xDA, 0xB1, 0x80, 0xD1, 0xE6, 0xE5,
+ 0x7A, 0xD5, 0xFE, 0x66, 0x8B, 0x38, 0xD7, 0x5E,
+ 0xD8, 0xE0, 0x67, 0xC0, 0xE0, 0x06, 0x10, 0xE6,
+ 0x18, 0xC7, 0x7A, 0xF4, 0xCF, 0xFD, 0xB2, 0xB4,
+ 0x1C, 0xF5, 0x46, 0x7D, 0xDF, 0x7C, 0x83, 0xA5,
+ 0xAB, 0xC3, 0x7C, 0xE1, 0x3F, 0x0A, 0xA3, 0xAA,
+ 0x37, 0x9F, 0x86, 0x8F, 0xAD, 0x26, 0xB8, 0x84,
+ 0xF4, 0x91, 0xF7, 0x19, 0x0A, 0x7B, 0x1B, 0x46,
+ 0x63, 0x43, 0x08, 0x41, 0x07, 0x0D, 0x19, 0xF1,
+ 0xFF, 0x8D, 0x23, 0xF1, 0xE8, 0x42, 0x54, 0x4C,
+ 0xBC, 0x89, 0x34, 0xA3, 0x90, 0xDC, 0x8A, 0x9F,
+ 0xA0, 0xFD, 0xC9, 0x65, 0xAB, 0x6B, 0x29, 0x71,
+ 0x6C, 0xA9, 0xF4, 0x77, 0x50, 0xA5, 0xEA, 0xBB,
+
+ 0x9C, 0xB1, 0xAA, 0x0D, 0xDB, 0xC1, 0x1A, 0x9C,
+ 0x5C, 0x98, 0x93, 0xD8, 0x01, 0xC7, 0xFE, 0x24,
+ 0xBC, 0x60, 0x5F, 0x0D, 0xA4, 0x50, 0xC2, 0x9D,
+ 0x11, 0x34, 0xDE, 0x31, 0xE9, 0xD2, 0x45, 0x49,
+ 0x6F, 0xC2, 0x91, 0x8C, 0x75, 0x1D, 0xB8, 0xD8,
+ 0x27, 0xA1, 0x5F, 0xF2, 0x66, 0xBA, 0xD2, 0x5C,
+ 0xD6, 0xBB, 0x5B, 0x45, 0x57, 0x08, 0xF3, 0x0A,
+ 0x5C, 0x58, 0xAA, 0x0B, 0x79, 0x12, 0x2F, 0x2D,
+ 0x42, 0x37, 0xCD, 0x5C, 0xB3, 0xF1, 0x8F, 0x34,
+ 0xE2, 0x61, 0xC3, 0x45, 0xFC, 0xFF, 0x96, 0x53,
+ 0x0B, 0x1A, 0x71, 0xB5, 0x5F, 0xA2, 0x12, 0x26,
+ 0x78, 0xCC, 0xBD, 0x5A, 0x84, 0x35, 0xAE, 0xF2,
+ 0xA3, 0xC3, 0x42, 0x5F, 0x51, 0x22, 0x77, 0x91,
+ 0x08, 0xDF, 0x1C, 0x68, 0xAE, 0x0F, 0x51, 0x79,
+ 0x4E, 0x75, 0xED, 0x8D, 0x55, 0x2A, 0x54, 0x88,
+ 0x97, 0xF8, 0x90, 0x24, 0x14, 0xE3, 0x07, 0x4D,
+ 0xCD, 0x26, 0x06, 0xA7, 0x35, 0xCF, 0x6A, 0x38,
+ 0xB7, 0x98, 0x2F, 0xA8, 0xAE, 0x6C, 0x3D, 0xB5,
+ 0x1E, 0x37, 0xD1, 0xE9, 0xD4, 0x53, 0x67, 0x4B,
+ 0xA4, 0xAE, 0xFA, 0x51, 0x01, 0x40, 0x8B, 0xD1,
+ 0x09, 0x74, 0x4C, 0x7F, 0xB2, 0xFA, 0xF9, 0xA8,
+ 0x27, 0xAF, 0xC8, 0x24, 0x2C, 0x31, 0xA1, 0xF6,
+ 0xF8, 0x81, 0xAC, 0xB4, 0x02, 0x83, 0x6F, 0x49,
+ 0xCF, 0xEC, 0xDF, 0x71, 0x5E, 0x2F, 0x33, 0x07,
+ 0xBA,
+
+ 0x55, 0xA8, 0x19, 0x38, 0x4C, 0x45, 0x5C, 0xF7,
+ 0x03, 0x9A, 0x21, 0x1B, 0xFF, 0xA8, 0xF7, 0x76,
+ 0x3E, 0xF2, 0x8E, 0xF1, 0xCD, 0x69, 0xDB, 0x0F,
+ 0xF6, 0x1C, 0x6A, 0x92, 0x71, 0xEF, 0x4A, 0x3E,
+ 0xCE, 0xF9, 0xEA, 0xAB, 0x76, 0x6B, 0x1E, 0xB5,
+ 0x02, 0x61, 0xA7, 0x02, 0x76, 0xBA, 0x6B, 0x1D,
+ 0xE5, 0xF0, 0x12, 0xDF, 0x1D, 0x61, 0x82, 0x90,
+ 0x91, 0xDA, 0x96, 0x60, 0x89, 0x88, 0x83, 0xCD,
+ 0xBF, 0xAC, 0xA8, 0x86, 0xC4, 0x7F, 0xA5, 0xA3,
+ 0x3E, 0x50, 0xC4, 0x8B, 0x30, 0xD8, 0x98, 0x89,
+ 0x0E, 0x10, 0xA3, 0x77, 0x64, 0xBF, 0x44, 0xE8,
+ 0x7B, 0xF4, 0x56, 0xA2, 0x87, 0x06, 0xF6, 0xF0,
+ 0x98, 0x77, 0x92, 0x5D, 0xED, 0x6A, 0x29, 0x33,
+ 0x22, 0x31, 0xD5, 0x3A, 0xD4, 0xDB, 0x11, 0x34,
+ 0x7D, 0xA0, 0xFC, 0x96, 0x54, 0x61, 0x16, 0x2C,
+ 0x48, 0x6C, 0x55, 0x2B, 0xE0, 0x8C, 0xE3, 0x7F,
+ 0x05, 0x32, 0xFB, 0xCE, 0xD4, 0x2F, 0x47, 0x54,
+ 0xE5, 0x9D, 0x6B, 0x68, 0x85, 0xF0, 0xD6, 0xCD,
+ 0xEA, 0xB6, 0x48, 0x59, 0xA8, 0xE6, 0x0B, 0x80,
+ 0x21, 0x2A, 0x62, 0x74, 0x1E, 0xD9, 0x11, 0x9A,
+ 0x16, 0x8A, 0xB0, 0xC5, 0x2C, 0xF2, 0x77, 0x80,
+ 0x0D, 0x74, 0x24, 0xE9, 0x29, 0x65, 0x47, 0x1F,
+ 0xEE, 0xF0, 0xA4, 0x26, 0xAF, 0xC5, 0x4B, 0x83,
+ 0x67, 0x23, 0x7C, 0x2E, 0x54, 0x29, 0x88, 0xD0,
+ 0x6A, 0xCB,
+
+ 0x35, 0x07, 0x1D, 0x30, 0xAA, 0x5F, 0xC8, 0x44,
+ 0xDA, 0x6D, 0xB6, 0xCB, 0x0B, 0xD6, 0x54, 0x54,
+ 0x48, 0x98, 0x07, 0xE6, 0xB0, 0x33, 0x48, 0xCF,
+ 0xB7, 0xAF, 0x58, 0xF6, 0x2A, 0x09, 0xD2, 0x7A,
+ 0xB5, 0xB4, 0x93, 0x6C, 0xC3, 0x83, 0xFB, 0x17,
+ 0xE5, 0xBF, 0xDD, 0xE3, 0x10, 0x37, 0x69, 0xF9,
+ 0x90, 0xEE, 0x65, 0x1E, 0x8F, 0x82, 0x14, 0xC5,
+ 0x38, 0xF3, 0x96, 0x22, 0x63, 0x81, 0xD4, 0x7A,
+ 0x23, 0x2E, 0x9A, 0xFD, 0xD4, 0xBB, 0xE1, 0x56,
+ 0xDD, 0xB6, 0xD0, 0x77, 0x0C, 0x88, 0x50, 0x18,
+ 0xE3, 0x25, 0xBC, 0x33, 0x36, 0xB0, 0xD9, 0x65,
+ 0xD2, 0xC2, 0xAA, 0x26, 0xB4, 0x52, 0xEF, 0x8B,
+ 0x19, 0x74, 0x14, 0x69, 0xB9, 0x60, 0x0B, 0x59,
+ 0x2C, 0xC7, 0x74, 0x0F, 0x6B, 0xF7, 0x5C, 0x4F,
+ 0xC7, 0xC8, 0xED, 0xFF, 0x1F, 0x02, 0x46, 0x46,
+ 0x93, 0x38, 0x6F, 0x34, 0x2A, 0x0C, 0xEC, 0x3E,
+ 0x3F, 0xAA, 0xA0, 0xEB, 0x43, 0x24, 0x84, 0x55,
+ 0xAF, 0x43, 0x08, 0x0B, 0xDD, 0x0D, 0x9D, 0x01,
+ 0x5C, 0x47, 0x27, 0x47, 0x3A, 0x0D, 0xA8, 0x27,
+ 0xAE, 0x04, 0x25, 0x27, 0x5D, 0xF6, 0x19, 0x6B,
+ 0x2E, 0x5A, 0x1B, 0x70, 0xBD, 0xB3, 0x44, 0x23,
+ 0x59, 0x4F, 0xE4, 0xA0, 0x02, 0x78, 0x22, 0xA6,
+ 0x25, 0xA8, 0x55, 0x59, 0xB5, 0xA0, 0x60, 0x47,
+ 0x57, 0x1F, 0x62, 0xC2, 0x16, 0x38, 0x7D, 0x86,
+ 0xB9, 0x0F, 0x8A,
+
+ 0xDD, 0x6E, 0xDE, 0x6B, 0x5B, 0x0B, 0xEA, 0xD1,
+ 0xB1, 0xB9, 0xD8, 0xA3, 0xCE, 0xE3, 0x95, 0x79,
+ 0x16, 0x68, 0x90, 0x54, 0x7A, 0xC4, 0x4E, 0x77,
+ 0x95, 0xD6, 0xBE, 0xAF, 0x0E, 0xE0, 0x88, 0xDA,
+ 0x28, 0xF2, 0xEA, 0x52, 0x77, 0xFE, 0x7F, 0xAA,
+ 0x3D, 0xD4, 0xCA, 0x1B, 0xBC, 0xAC, 0xC5, 0x0D,
+ 0xE2, 0x50, 0x70, 0x57, 0x12, 0x14, 0x54, 0x97,
+ 0x22, 0x3E, 0x43, 0x82, 0x0F, 0xA1, 0xA8, 0x93,
+ 0x4A, 0xD3, 0x7E, 0xE1, 0x1E, 0xBE, 0xD5, 0x3E,
+ 0x36, 0x61, 0xB1, 0x0A, 0x85, 0x6F, 0x3B, 0xF4,
+ 0x60, 0x39, 0xEE, 0xE5, 0x81, 0x88, 0xC2, 0x6E,
+ 0x24, 0xAC, 0xBD, 0x0C, 0x25, 0xE7, 0xAB, 0xB0,
+ 0xC8, 0xA1, 0x8F, 0x09, 0xE3, 0xCA, 0x77, 0xE3,
+ 0x50, 0x80, 0x6A, 0x42, 0x94, 0x2C, 0x43, 0x85,
+ 0x71, 0xB8, 0x4A, 0xCC, 0xBA, 0x0C, 0x5D, 0xBF,
+ 0x2C, 0xF8, 0x36, 0x5D, 0x79, 0xFB, 0x3C, 0x11,
+ 0x15, 0x7C, 0x47, 0xDD, 0xC7, 0x26, 0x71, 0x44,
+ 0xAF, 0x17, 0xAE, 0x74, 0xF1, 0xC5, 0xE0, 0x00,
+ 0x5C, 0xF0, 0x96, 0x38, 0x86, 0x1A, 0x7F, 0xA1,
+ 0xBC, 0x0E, 0x32, 0xCA, 0x54, 0xBF, 0x5F, 0xEA,
+ 0x76, 0x31, 0x1B, 0x1B, 0x70, 0xE5, 0xB9, 0xA8,
+ 0x18, 0x58, 0xF4, 0x31, 0x92, 0xDD, 0x25, 0xB6,
+ 0xF5, 0xC1, 0x6B, 0x0D, 0xFC, 0x97, 0x29, 0xD1,
+ 0x6F, 0xE2, 0xCD, 0xC6, 0x41, 0x24, 0x28, 0x68,
+ 0x42, 0x23, 0x34, 0xF5,
+
+ 0xC7, 0xD2, 0x23, 0x12, 0x22, 0x4E, 0x47, 0x8E,
+ 0xB9, 0x0E, 0x31, 0x80, 0xA3, 0xB3, 0x72, 0xE1,
+ 0xB4, 0xE6, 0x43, 0x4C, 0x9C, 0xDE, 0xBD, 0x34,
+ 0x79, 0xD8, 0x2D, 0x82, 0xA2, 0x79, 0x64, 0x54,
+ 0x13, 0x9C, 0xFC, 0x21, 0x3A, 0x7C, 0xFC, 0x84,
+ 0x87, 0xB6, 0x94, 0xD8, 0x8E, 0x6A, 0xBD, 0xA7,
+ 0xC5, 0x2E, 0xC6, 0x88, 0x46, 0xF9, 0xA3, 0xFE,
+ 0x66, 0x6D, 0x10, 0xB3, 0x07, 0x27, 0xDE, 0xDC,
+ 0x84, 0xEC, 0xFB, 0x15, 0xC7, 0x6C, 0x9E, 0x3E,
+ 0x03, 0x41, 0x29, 0x8F, 0x06, 0xDB, 0xF1, 0x5E,
+ 0x21, 0xB7, 0x5E, 0x42, 0x9C, 0x7D, 0x21, 0xC8,
+ 0x78, 0x5E, 0x6E, 0x19, 0x77, 0x21, 0x41, 0xF6,
+ 0x5D, 0x2F, 0x6A, 0xC1, 0xCB, 0xB8, 0x62, 0x4B,
+ 0xDD, 0xD4, 0xBE, 0x2E, 0xAD, 0x05, 0x6E, 0x4F,
+ 0x96, 0x4C, 0x02, 0x5D, 0x75, 0xE7, 0x0E, 0x50,
+ 0xA5, 0x45, 0xB3, 0x47, 0xAC, 0xAE, 0xED, 0x0C,
+ 0x94, 0x6A, 0x5E, 0x4A, 0x66, 0xE9, 0x2A, 0x2A,
+ 0x5B, 0x00, 0xA7, 0xEC, 0xDE, 0xE7, 0xE8, 0xAA,
+ 0x01, 0x51, 0x4F, 0x2B, 0x67, 0x95, 0x2E, 0xA7,
+ 0xE3, 0x05, 0x9D, 0x45, 0x40, 0x68, 0x7F, 0xBB,
+ 0x98, 0xCB, 0x54, 0x8C, 0xEB, 0x29, 0xAD, 0xE2,
+ 0xA6, 0x8C, 0xBB, 0x33, 0xCD, 0xB2, 0x79, 0x6E,
+ 0x37, 0x01, 0xEB, 0xF6, 0x19, 0x70, 0x08, 0x08,
+ 0x17, 0x4F, 0x8E, 0x45, 0x2A, 0x8A, 0x97, 0x91,
+ 0x8D, 0x4F, 0x53, 0x4B, 0x3F,
+
+ 0xCA, 0x0D, 0x28, 0x4B, 0x0A, 0x4D, 0xD4, 0x03,
+ 0xDA, 0xAA, 0x7E, 0x33, 0x7D, 0x98, 0x9D, 0xE0,
+ 0x5B, 0x29, 0x94, 0x19, 0xA4, 0xD8, 0xC7, 0xF8,
+ 0x11, 0xF0, 0xD9, 0x18, 0x9A, 0x17, 0x1A, 0x14,
+ 0xE1, 0x4E, 0x4F, 0x09, 0x45, 0x7D, 0x17, 0xE9,
+ 0xB7, 0xA2, 0x6B, 0x0A, 0xE6, 0x17, 0x57, 0x05,
+ 0x24, 0xDC, 0xC6, 0x75, 0xAE, 0xBC, 0xAE, 0x32,
+ 0x1B, 0x60, 0x5A, 0x5D, 0x77, 0xB4, 0x42, 0x48,
+ 0x99, 0xE7, 0xB5, 0xEB, 0xE5, 0x7A, 0x10, 0x93,
+ 0x5D, 0x81, 0xCA, 0x01, 0x2F, 0x41, 0xD4, 0x0F,
+ 0xDE, 0xBE, 0xC4, 0x59, 0xC3, 0xDB, 0xDE, 0xF3,
+ 0x14, 0xFC, 0xC5, 0x8B, 0x22, 0xCC, 0x6A, 0x3F,
+ 0x0C, 0xCC, 0x53, 0x3D, 0x39, 0x0C, 0x83, 0xED,
+ 0x51, 0x54, 0x4A, 0xD9, 0x2D, 0x0C, 0x5E, 0x1D,
+ 0x0B, 0x82, 0x73, 0x0C, 0x41, 0xCD, 0x8D, 0xD0,
+ 0xD9, 0xD3, 0x7C, 0x8D, 0x3D, 0xFA, 0xA9, 0x51,
+ 0xE5, 0x13, 0x8B, 0x81, 0x32, 0x62, 0xAB, 0xB6,
+ 0xB1, 0xF2, 0x1C, 0x5C, 0xE6, 0x9A, 0xB0, 0x83,
+ 0x40, 0x92, 0xB8, 0x85, 0x22, 0x7E, 0x53, 0x9A,
+ 0x0F, 0x87, 0xDD, 0xBA, 0x20, 0x83, 0xE4, 0x93,
+ 0xDE, 0x35, 0x8E, 0xBD, 0x2F, 0xA3, 0x04, 0xF2,
+ 0x87, 0x62, 0x9E, 0xD9, 0x72, 0xBC, 0xC7, 0x0C,
+ 0x8F, 0x6F, 0x48, 0x93, 0x0D, 0x48, 0x9B, 0x21,
+ 0xA7, 0xD4, 0x12, 0x0C, 0x06, 0x61, 0x9D, 0xC2,
+ 0x45, 0x51, 0x17, 0x6D, 0xD2, 0x95,
+
+ 0x15, 0x94, 0x79, 0xF5, 0xEB, 0x7F, 0xDD, 0x18,
+ 0x2E, 0x9C, 0x4B, 0xA0, 0xD2, 0x3D, 0xEF, 0x37,
+ 0x82, 0xDB, 0xDC, 0xFB, 0x8D, 0x07, 0x87, 0x30,
+ 0x89, 0x79, 0x31, 0xB1, 0x27, 0xAF, 0x6B, 0x9B,
+ 0x0C, 0xAB, 0xA3, 0x72, 0xA4, 0xE3, 0x96, 0x7B,
+ 0x61, 0x4F, 0xB4, 0x0D, 0xD1, 0x64, 0x9D, 0xD5,
+ 0x3D, 0x0F, 0x24, 0x3C, 0xFF, 0x39, 0xA3, 0x08,
+ 0x7E, 0xD0, 0x4A, 0x14, 0xF2, 0x16, 0x08, 0x12,
+ 0x58, 0x6F, 0xE4, 0xC3, 0xEE, 0x77, 0xDA, 0xF0,
+ 0x21, 0x0E, 0x8A, 0xFB, 0x19, 0x46, 0x08, 0xCF,
+ 0x47, 0x93, 0x76, 0xE8, 0x15, 0x7F, 0x07, 0xC7,
+ 0x44, 0x4A, 0x35, 0xA9, 0x65, 0x58, 0xF6, 0x21,
+ 0xCA, 0x2E, 0xAD, 0xE1, 0x21, 0xE2, 0x25, 0x8F,
+ 0x87, 0xA4, 0xFD, 0xE1, 0xEF, 0xE9, 0x25, 0x70,
+ 0x7E, 0x41, 0x4D, 0x5A, 0x20, 0xC6, 0x0C, 0xD4,
+ 0xE5, 0x49, 0xF3, 0xB9, 0xDB, 0xE5, 0xCE, 0x21,
+ 0x1D, 0xE5, 0xA9, 0x73, 0x5E, 0x91, 0xFA, 0x86,
+ 0x5A, 0x25, 0x52, 0x27, 0xF5, 0x4C, 0x92, 0xC1,
+ 0x14, 0x52, 0x0E, 0x78, 0x6E, 0xCD, 0x8F, 0x0F,
+ 0xD5, 0x40, 0x42, 0x01, 0xD1, 0x6A, 0xD2, 0xCE,
+ 0xD8, 0xC0, 0x6A, 0x3E, 0x82, 0xF0, 0x41, 0x0D,
+ 0x44, 0x24, 0xE2, 0x43, 0xA3, 0xE8, 0x68, 0x12,
+ 0x46, 0x2E, 0x7A, 0x72, 0x04, 0xE0, 0xE6, 0x38,
+ 0x4D, 0x62, 0x7F, 0x02, 0x59, 0x17, 0x8F, 0xB9,
+ 0x75, 0x74, 0x25, 0x7F, 0x95, 0xBF, 0x9C,
+
+ 0xC5, 0x38, 0x2D, 0xA3, 0x3D, 0xF8, 0x27, 0x28,
+ 0x56, 0x3E, 0x35, 0x24, 0x8D, 0x8F, 0x56, 0xBD,
+ 0xA9, 0x6D, 0x58, 0x99, 0x12, 0xC7, 0xAB, 0x4A,
+ 0xE0, 0xF7, 0xDE, 0x1E, 0xF0, 0x40, 0x89, 0x0C,
+ 0xE4, 0x7B, 0xF8, 0x7B, 0x8C, 0x1B, 0x6F, 0xC1,
+ 0xD4, 0x6E, 0xEF, 0x45, 0x2E, 0x7E, 0x03, 0x0F,
+ 0x3B, 0x0F, 0x48, 0x28, 0x8D, 0x8C, 0xAF, 0x9E,
+ 0xB3, 0x55, 0x6B, 0xA7, 0xAA, 0x03, 0x94, 0x21,
+ 0xED, 0x7A, 0x92, 0x81, 0x12, 0x37, 0xAF, 0x4B,
+ 0xE1, 0x34, 0x62, 0xC6, 0x7D, 0x5E, 0xA8, 0xD6,
+ 0x9A, 0xB8, 0x12, 0xF0, 0xB8, 0x7E, 0x92, 0x88,
+ 0xDB, 0x67, 0x97, 0x56, 0x88, 0xA4, 0x22, 0x18,
+ 0xFC, 0xC3, 0xCD, 0x1B, 0x12, 0x09, 0xC9, 0xD6,
+ 0x71, 0xE1, 0x76, 0xED, 0x95, 0x61, 0x96, 0xF9,
+ 0xB1, 0xFA, 0x16, 0x9F, 0xDC, 0x3A, 0x3C, 0x9A,
+ 0xFB, 0x25, 0x0A, 0x0C, 0x8B, 0xFB, 0xD1, 0x7E,
+ 0x13, 0x27, 0x5B, 0x24, 0x95, 0xC4, 0x6B, 0xAC,
+ 0x32, 0xB5, 0x1D, 0xC9, 0x96, 0x67, 0x84, 0x43,
+ 0x5C, 0xAD, 0xD2, 0xF2, 0x15, 0xDA, 0x83, 0x84,
+ 0x71, 0xB2, 0x14, 0x04, 0x20, 0xDD, 0x04, 0x78,
+ 0x6E, 0xCD, 0x7F, 0x73, 0xD1, 0xAD, 0xBE, 0xD4,
+ 0x4F, 0xED, 0xF8, 0xE9, 0xEA, 0x07, 0xBD, 0xB7,
+ 0xDD, 0x0F, 0xFB, 0xF5, 0x88, 0x6A, 0x3E, 0x8A,
+ 0xCD, 0x79, 0xBA, 0xDE, 0x98, 0xB3, 0x74, 0x3D,
+ 0x0F, 0x92, 0x40, 0x10, 0xE4, 0x26, 0x85, 0x2D,
+
+ 0x0E, 0x46, 0xBD, 0x8B, 0xDC, 0xE8, 0x28, 0x6A,
+ 0x31, 0x78, 0xE6, 0xDE, 0x37, 0xC0, 0x68, 0x2D,
+ 0xE0, 0x38, 0xD0, 0x2F, 0x28, 0xBB, 0xA2, 0xF4,
+ 0x8F, 0x82, 0x35, 0xDF, 0x0F, 0xB9, 0x31, 0x98,
+ 0xF6, 0x03, 0x66, 0x80, 0xCF, 0xDA, 0xF0, 0x0B,
+ 0x4C, 0x62, 0x2F, 0x6E, 0x7A, 0x1B, 0x80, 0x98,
+ 0x7A, 0xDB, 0x1F, 0x2B, 0xC2, 0x2F, 0x96, 0x80,
+ 0x58, 0x98, 0x21, 0xFC, 0xBB, 0x1A, 0x13, 0xAF,
+ 0x56, 0xA5, 0x4A, 0x89, 0xDB, 0xF0, 0x28, 0x97,
+ 0x43, 0xB6, 0x45, 0xBF, 0x58, 0x76, 0x78, 0x8A,
+ 0x83, 0xF8, 0x6E, 0xC1, 0x90, 0x99, 0x59, 0x0A,
+ 0xF2, 0x1E, 0x95, 0x8A, 0x13, 0x58, 0xC0, 0xC7,
+ 0x8F, 0x27, 0xD9, 0x53, 0xEC, 0xD0, 0x24, 0xFC,
+ 0x83, 0x60, 0x74, 0x24, 0x2D, 0xD5, 0xE5, 0x51,
+ 0x27, 0x0E, 0x62, 0x17, 0xD4, 0xAA, 0xF1, 0x30,
+ 0x6F, 0x35, 0x4C, 0xE0, 0x91, 0x2D, 0xDA, 0x11,
+ 0x68, 0xDF, 0x6F, 0xEA, 0x29, 0xC0, 0xB4, 0x75,
+ 0x04, 0x4E, 0xB7, 0x49, 0x47, 0x19, 0xA1, 0x7F,
+ 0x99, 0x0B, 0x45, 0x95, 0x3F, 0x6A, 0x97, 0x8B,
+ 0xA8, 0x27, 0x1C, 0xBF, 0x07, 0x7D, 0x30, 0xD9,
+ 0x97, 0xD7, 0xA5, 0x2D, 0x22, 0x23, 0xF7, 0x1D,
+ 0xFD, 0x4A, 0xE9, 0xA8, 0xFD, 0x10, 0xE4, 0xEF,
+ 0x0F, 0xBB, 0x54, 0x2B, 0xFC, 0x74, 0xDE, 0x55,
+ 0xF7, 0x51, 0xBF, 0x8B, 0x73, 0x38, 0xF8, 0x5E,
+ 0xFF, 0x8C, 0x96, 0xFF, 0xFA, 0x82, 0x67, 0xC7,
+ 0xA6,
+
+ 0x78, 0xC3, 0xA1, 0xCB, 0x49, 0x80, 0x93, 0x83,
+ 0x6D, 0x3D, 0x8C, 0xB6, 0x38, 0x79, 0x45, 0xCF,
+ 0x65, 0x32, 0x71, 0xE6, 0x00, 0x24, 0x23, 0x45,
+ 0x47, 0x37, 0x84, 0x54, 0x1B, 0x7E, 0x25, 0x5B,
+ 0x86, 0xA5, 0x55, 0x07, 0xB4, 0x0B, 0xCD, 0x23,
+ 0x6B, 0xF3, 0x33, 0xCB, 0xCA, 0x7C, 0xBC, 0x7F,
+ 0x43, 0x50, 0x02, 0xA2, 0x45, 0x1C, 0xD3, 0x32,
+ 0x7C, 0x28, 0x6D, 0xA1, 0x24, 0x2A, 0x58, 0x29,
+ 0xC1, 0xB2, 0x6C, 0x71, 0x1A, 0xA4, 0xA9, 0xB3,
+ 0x27, 0xAB, 0xBC, 0xC6, 0x9F, 0x9D, 0x92, 0xB6,
+ 0x70, 0x99, 0xA6, 0x9B, 0xAD, 0x8A, 0x59, 0xC9,
+ 0x08, 0xE0, 0xFB, 0x92, 0xB0, 0x0B, 0x03, 0x75,
+ 0xBA, 0xC0, 0x88, 0x56, 0xF2, 0x8B, 0xCD, 0x22,
+ 0xB8, 0x2B, 0xEA, 0xD8, 0x79, 0xD1, 0xA5, 0xF4,
+ 0x98, 0xEF, 0x71, 0xE9, 0xFE, 0xBC, 0x0F, 0xEA,
+ 0x5B, 0x8D, 0x96, 0xF6, 0xB7, 0x03, 0xEF, 0xA6,
+ 0x61, 0x05, 0x8F, 0xB3, 0x0D, 0xB0, 0xCA, 0xC1,
+ 0xCF, 0x25, 0xB2, 0x87, 0x98, 0x13, 0xB8, 0xEC,
+ 0xA8, 0x54, 0xF6, 0xF5, 0x5F, 0xB2, 0x11, 0x52,
+ 0x14, 0xD7, 0x9E, 0x36, 0x93, 0x62, 0x3B, 0x24,
+ 0x92, 0x9C, 0x63, 0xB7, 0x2D, 0x18, 0xAA, 0x10,
+ 0x89, 0x84, 0x29, 0x16, 0xF0, 0xDF, 0x7C, 0x31,
+ 0x0C, 0x3E, 0x25, 0xB3, 0x72, 0x50, 0xE3, 0x51,
+ 0xDC, 0x12, 0x58, 0xA7, 0xED, 0x38, 0x43, 0x92,
+ 0x1B, 0xA5, 0x54, 0xE1, 0xC6, 0x56, 0x30, 0x65,
+ 0x0A, 0xA5,
+
+ 0x02, 0xF5, 0xEC, 0x03, 0x39, 0xF9, 0x74, 0xC8,
+ 0xAC, 0xC7, 0xF7, 0xE5, 0x62, 0x30, 0xB3, 0x0E,
+ 0xBA, 0x02, 0xD6, 0x48, 0x76, 0x84, 0xDC, 0x9F,
+ 0xF0, 0x79, 0x39, 0x06, 0xA9, 0x82, 0x53, 0x00,
+ 0xAB, 0x09, 0x0C, 0x16, 0xDE, 0xC1, 0x05, 0xC8,
+ 0x2C, 0x92, 0x02, 0x61, 0xEA, 0x87, 0x8C, 0xFC,
+ 0x8A, 0x0B, 0x9F, 0x04, 0x9F, 0x51, 0x5F, 0x7B,
+ 0x4F, 0xAC, 0xF1, 0x4F, 0x9A, 0x29, 0x61, 0x42,
+ 0x8C, 0xD7, 0x23, 0x49, 0x63, 0xEB, 0xFD, 0x2C,
+ 0xDC, 0x76, 0xF1, 0xF0, 0xC8, 0xA2, 0x97, 0x5C,
+ 0x20, 0x23, 0x7C, 0x9F, 0x5D, 0xDE, 0x59, 0x87,
+ 0x3A, 0x33, 0xE6, 0x77, 0x83, 0xE8, 0xF7, 0xA8,
+ 0x31, 0x7E, 0xFA, 0x02, 0x79, 0x96, 0x13, 0xCB,
+ 0x08, 0xB3, 0x0E, 0x18, 0x2E, 0x2C, 0x48, 0x1B,
+ 0x8D, 0xF7, 0x40, 0x0F, 0xD0, 0x95, 0x29, 0x99,
+ 0xA9, 0x8C, 0xF5, 0xBA, 0xC3, 0xE7, 0x1E, 0x3F,
+ 0x34, 0x13, 0x02, 0x24, 0xF0, 0x4E, 0xC6, 0xCD,
+ 0xEE, 0xA1, 0xF0, 0x0F, 0xAE, 0xB8, 0x31, 0x0F,
+ 0x5F, 0x34, 0x4F, 0xAC, 0x17, 0x52, 0x26, 0x84,
+ 0xA0, 0x65, 0x88, 0x2E, 0xA2, 0x75, 0xC0, 0x18,
+ 0x6A, 0x2C, 0xDD, 0x0F, 0xF9, 0x0E, 0xFA, 0x56,
+ 0xBB, 0x71, 0xAD, 0x69, 0xCB, 0x96, 0x31, 0xCF,
+ 0x66, 0x1C, 0x87, 0x71, 0x77, 0x11, 0x39, 0xB7,
+ 0xE9, 0x25, 0x7A, 0x88, 0x8A, 0x0C, 0xE9, 0xCD,
+ 0x0F, 0xB9, 0x82, 0x18, 0x66, 0x2A, 0xD1, 0x91,
+ 0xD9, 0x4F, 0x8D,
+
+ 0xE9, 0xF8, 0x7F, 0xAE, 0x1B, 0x66, 0x68, 0x95,
+ 0x73, 0xE2, 0x74, 0x01, 0xE1, 0x7D, 0x2A, 0x45,
+ 0xC0, 0x88, 0x27, 0xB0, 0x1A, 0x6F, 0xD0, 0x5E,
+ 0xA6, 0x05, 0x9D, 0x18, 0xB8, 0xA2, 0x86, 0x0E,
+ 0xB3, 0xF7, 0x79, 0xC3, 0x41, 0xBE, 0x1D, 0x34,
+ 0x69, 0x19, 0x07, 0x2F, 0x81, 0x48, 0xFC, 0xC1,
+ 0x35, 0xA4, 0x98, 0xFF, 0xAA, 0xA7, 0xF9, 0xC7,
+ 0x32, 0x63, 0xBB, 0x56, 0xA7, 0xBE, 0x31, 0x88,
+ 0xA1, 0x35, 0x57, 0x17, 0x1B, 0x00, 0x5A, 0x0C,
+ 0xAF, 0x48, 0xE8, 0xA6, 0x63, 0x5F, 0x6B, 0xB9,
+ 0x4D, 0x44, 0x0E, 0xCB, 0xA2, 0xDB, 0x7E, 0xBD,
+ 0xC1, 0x99, 0x7A, 0x02, 0xAE, 0xDF, 0x01, 0xA6,
+ 0x19, 0x8A, 0xA0, 0x91, 0xA8, 0x4E, 0x34, 0xF6,
+ 0x4A, 0x53, 0xD3, 0x44, 0xF6, 0x3C, 0x5A, 0x2D,
+ 0x16, 0xAD, 0x5F, 0x09, 0x0B, 0xE2, 0xE8, 0xD0,
+ 0xFE, 0x09, 0x6F, 0x7A, 0xDB, 0x86, 0x57, 0xA9,
+ 0x7B, 0x06, 0x7D, 0xC5, 0x99, 0x4C, 0xA5, 0xE2,
+ 0xEA, 0x18, 0x0A, 0xFD, 0xB6, 0xF2, 0x03, 0xEA,
+ 0xEC, 0xAF, 0x7B, 0xA1, 0x9C, 0x31, 0xDF, 0x17,
+ 0x74, 0x6D, 0x01, 0x9E, 0xBF, 0x76, 0x63, 0x2D,
+ 0x5B, 0xA0, 0xF6, 0xD1, 0xC2, 0x01, 0x40, 0xDF,
+ 0xE1, 0x81, 0xD6, 0xCB, 0x67, 0xC7, 0x96, 0x6C,
+ 0xE6, 0x34, 0x9E, 0xA5, 0x23, 0xCA, 0x9B, 0x06,
+ 0x96, 0x45, 0xFA, 0xB8, 0x96, 0x3A, 0x66, 0x32,
+ 0x5F, 0xF1, 0x92, 0xA1, 0x64, 0xF8, 0x2B, 0x90,
+ 0x65, 0x5D, 0xD7, 0xF8,
+
+ 0x8F, 0xEC, 0x60, 0x90, 0x57, 0x5B, 0x8B, 0x0F,
+ 0xF5, 0xF9, 0xF1, 0xA6, 0x11, 0x9A, 0xE5, 0x47,
+ 0x50, 0x3A, 0x7D, 0x92, 0x1C, 0x2D, 0xBE, 0x3F,
+ 0x0B, 0x75, 0x18, 0x78, 0xD1, 0x29, 0xBA, 0x37,
+ 0x3F, 0xD6, 0x89, 0xE6, 0x14, 0x54, 0x58, 0x70,
+ 0x0F, 0x17, 0x62, 0x4E, 0xE3, 0x8E, 0xC0, 0x18,
+ 0x7B, 0x5C, 0xCB, 0x31, 0x95, 0x16, 0x9E, 0xEC,
+ 0x0B, 0x7B, 0xF4, 0x1D, 0xC6, 0x30, 0xB4, 0xBD,
+ 0xAA, 0x29, 0x33, 0x94, 0xCC, 0x30, 0x98, 0x44,
+ 0x20, 0x4E, 0xF3, 0x50, 0x9C, 0x75, 0x5C, 0xB0,
+ 0xB9, 0x1F, 0x60, 0xDF, 0xFA, 0x57, 0xAF, 0xC1,
+ 0x69, 0x50, 0xFD, 0x09, 0x9B, 0x62, 0xEB, 0xE5,
+ 0x9C, 0x09, 0xAB, 0x83, 0x34, 0xDE, 0x9F, 0x48,
+ 0xF7, 0x2B, 0x21, 0xB7, 0xC5, 0x90, 0x15, 0xFF,
+ 0x9D, 0x5F, 0xD7, 0x5A, 0x4F, 0x6D, 0xB7, 0x8C,
+ 0xD5, 0x74, 0x17, 0xEB, 0xD2, 0xF5, 0xE2, 0xCF,
+ 0x6E, 0xE0, 0xE3, 0xCD, 0xD7, 0x11, 0xD7, 0xA6,
+ 0x89, 0xF4, 0xDE, 0xEF, 0xEB, 0x77, 0xCD, 0xA3,
+ 0x2C, 0x1F, 0xDF, 0xED, 0x93, 0xA6, 0x51, 0xC8,
+ 0xD4, 0x45, 0x72, 0x11, 0x7F, 0xC8, 0x68, 0x86,
+ 0x4B, 0x6E, 0x13, 0x92, 0x2B, 0xDA, 0x6F, 0xE4,
+ 0x86, 0xBB, 0xF4, 0x71, 0x8E, 0xA4, 0x2A, 0x55,
+ 0x3C, 0xC6, 0x37, 0x67, 0x96, 0xFF, 0x40, 0xF9,
+ 0x1E, 0xDD, 0x95, 0x5A, 0x89, 0x0C, 0x07, 0x59,
+ 0x90, 0x4F, 0xCF, 0x83, 0xE8, 0x0B, 0x93, 0x73,
+ 0xAA, 0x8A, 0x15, 0x0A, 0x21,
+
+ 0x8F, 0xB7, 0xC6, 0xB8, 0x22, 0xAE, 0x29, 0x71,
+ 0x39, 0xA5, 0x99, 0xC3, 0x6F, 0xBD, 0x8D, 0xF2,
+ 0x74, 0x24, 0x7E, 0xFF, 0x4B, 0x35, 0x63, 0xF4,
+ 0xD2, 0xA8, 0x55, 0xCD, 0x1A, 0x1A, 0x40, 0x64,
+ 0x45, 0x61, 0xD8, 0x26, 0xA0, 0x23, 0x3E, 0xDC,
+ 0x57, 0x05, 0xB8, 0xC4, 0xC0, 0x0C, 0xF4, 0x2E,
+ 0x3F, 0xBE, 0x36, 0xFB, 0x84, 0xDF, 0x5A, 0x19,
+ 0x87, 0x78, 0x6B, 0x31, 0x2D, 0xB5, 0x03, 0x98,
+ 0x92, 0x3C, 0x5F, 0xD7, 0x5F, 0x06, 0x2A, 0x00,
+ 0x5C, 0x7C, 0xF1, 0x4F, 0x70, 0x36, 0xBB, 0xE0,
+ 0xDC, 0x5B, 0x9A, 0x10, 0x87, 0x13, 0x05, 0x58,
+ 0xB2, 0x9C, 0xEB, 0xFE, 0xCF, 0x82, 0x03, 0x18,
+ 0x6A, 0x37, 0x8D, 0x11, 0xD9, 0x15, 0x1E, 0x27,
+ 0x54, 0x8E, 0x7A, 0x30, 0x13, 0xD8, 0x1A, 0xBB,
+ 0x6C, 0xAD, 0xC4, 0xFD, 0x61, 0x2E, 0x03, 0xEB,
+ 0x2C, 0x2D, 0x01, 0x4A, 0x3A, 0xCA, 0xDF, 0x23,
+ 0x8E, 0x39, 0x81, 0x6D, 0x62, 0xEE, 0x12, 0x89,
+ 0xC6, 0xA3, 0x1D, 0x38, 0xA9, 0xDE, 0x5D, 0x1C,
+ 0x3F, 0xAE, 0x79, 0xAC, 0x2A, 0x5B, 0xCD, 0x94,
+ 0x9F, 0xE3, 0xB8, 0x93, 0x21, 0x4E, 0x0E, 0xB4,
+ 0x78, 0xE6, 0xC2, 0x69, 0x7D, 0x58, 0x26, 0xDD,
+ 0xE1, 0xC0, 0xAB, 0xF9, 0x9F, 0xDE, 0xB0, 0xB5,
+ 0x24, 0x78, 0x4C, 0x5A, 0x42, 0x91, 0x8E, 0x03,
+ 0x95, 0xAA, 0x08, 0xD4, 0x56, 0x6D, 0x64, 0x41,
+ 0xC7, 0xC9, 0x2E, 0xEC, 0xE7, 0x1A, 0xEB, 0xE8,
+ 0x24, 0x8D, 0xE3, 0x31, 0xA5, 0x11,
+
+ 0x05, 0x2F, 0xC0, 0x7D, 0xD7, 0xC5, 0x12, 0xF3,
+ 0x37, 0x94, 0x79, 0xEF, 0x44, 0xEE, 0xB0, 0xD0,
+ 0xED, 0x39, 0xCB, 0x5E, 0x64, 0xE9, 0x83, 0xD2,
+ 0x76, 0xF0, 0x65, 0x47, 0x25, 0x1D, 0x0D, 0x6B,
+ 0x16, 0x23, 0x98, 0xE5, 0x1D, 0xF2, 0xB1, 0x68,
+ 0x0D, 0xBA, 0xFE, 0x9D, 0x1A, 0x1D, 0xBA, 0x5F,
+ 0x92, 0x6F, 0x17, 0x76, 0xF5, 0xB3, 0xBA, 0x5A,
+ 0x71, 0x0C, 0x72, 0xFA, 0x32, 0xCC, 0x7B, 0x17,
+ 0x52, 0xB7, 0xF9, 0x86, 0x70, 0xF7, 0x39, 0x22,
+ 0xA1, 0xF6, 0xB3, 0xAA, 0xE9, 0xC5, 0x8B, 0x69,
+ 0xE4, 0x48, 0xD2, 0xAA, 0x8E, 0xAF, 0x7C, 0xE5,
+ 0x77, 0xE1, 0x33, 0xEC, 0x30, 0x20, 0xB8, 0xCD,
+ 0x3E, 0xD6, 0xB6, 0xD0, 0x64, 0x86, 0x39, 0x01,
+ 0x0D, 0x4F, 0xAB, 0xF7, 0x7B, 0xBE, 0x97, 0x21,
+ 0xCD, 0x96, 0x69, 0x16, 0x73, 0x61, 0x7D, 0x84,
+ 0x21, 0x3A, 0xA0, 0x07, 0xDE, 0xCA, 0x17, 0x0E,
+ 0x82, 0xA4, 0x8B, 0x2D, 0xE4, 0x99, 0x11, 0x3C,
+ 0x3C, 0x5B, 0x16, 0xB8, 0x00, 0xEE, 0xD1, 0xDF,
+ 0x68, 0x30, 0x0E, 0x12, 0x5E, 0x12, 0x4F, 0x1B,
+ 0xBE, 0xC2, 0x9B, 0x99, 0x64, 0xDB, 0xCE, 0x29,
+ 0xE5, 0x8E, 0x66, 0x96, 0x65, 0x37, 0x6E, 0xE2,
+ 0xE9, 0x05, 0x34, 0x56, 0x8D, 0xDF, 0x24, 0x34,
+ 0x09, 0x77, 0xB0, 0x76, 0xDD, 0x1E, 0x76, 0x5D,
+ 0x67, 0x7D, 0xCC, 0xCF, 0xB2, 0x7E, 0x15, 0x5E,
+ 0xE0, 0x4E, 0x80, 0x4B, 0xE0, 0xD2, 0x5A, 0xD4,
+ 0x1F, 0x5F, 0x6E, 0x65, 0x9C, 0x07, 0xBD,
+
+ 0x08, 0x49, 0x9F, 0x83, 0x46, 0x0F, 0x0E, 0x04,
+ 0x94, 0x6C, 0x3F, 0x75, 0x4D, 0x98, 0xE5, 0x5D,
+ 0x12, 0xCB, 0xF6, 0x53, 0x0D, 0xFD, 0x30, 0x75,
+ 0x92, 0x02, 0xA9, 0x69, 0xD3, 0x71, 0xBC, 0x28,
+ 0xBC, 0x18, 0x88, 0x48, 0x27, 0x0B, 0x3B, 0x5C,
+ 0x2C, 0xFF, 0x7C, 0xFA, 0xB1, 0x02, 0x00, 0x79,
+ 0x6D, 0x8A, 0x39, 0x3F, 0xF2, 0x11, 0xA8, 0xA3,
+ 0x95, 0x68, 0xCA, 0x97, 0x1E, 0xD9, 0x80, 0xD8,
+ 0x9D, 0x4C, 0x62, 0x3E, 0xA5, 0xD0, 0x61, 0xE3,
+ 0x0D, 0x3D, 0xBA, 0xE7, 0x0E, 0x7F, 0x23, 0xBF,
+ 0x3D, 0x04, 0xB4, 0x1F, 0x20, 0x49, 0x5A, 0x40,
+ 0x50, 0x59, 0x2C, 0x09, 0x05, 0x5B, 0x8D, 0x07,
+ 0xA9, 0x79, 0x75, 0x13, 0xFF, 0xB5, 0x33, 0x58,
+ 0x41, 0x5D, 0x1D, 0xF1, 0x39, 0x54, 0x3A, 0x41,
+ 0x09, 0xDB, 0x5F, 0xC7, 0x5F, 0x7A, 0xE6, 0x27,
+ 0xA4, 0xFF, 0x20, 0xE8, 0x5F, 0x25, 0x89, 0xCB,
+ 0x77, 0x8D, 0xD7, 0x79, 0x16, 0x50, 0x68, 0xE0,
+ 0x24, 0xEC, 0x87, 0x60, 0xC2, 0x75, 0x87, 0xB8,
+ 0xAD, 0x66, 0x64, 0xF1, 0x6B, 0x01, 0x7E, 0xB0,
+ 0xE3, 0x79, 0x7E, 0x84, 0x29, 0x51, 0x47, 0x24,
+ 0xB9, 0x5D, 0xC6, 0x13, 0xEC, 0x0D, 0x5E, 0x8B,
+ 0x3E, 0x68, 0x97, 0x74, 0xB5, 0x1C, 0xE6, 0x9E,
+ 0x74, 0xD1, 0x9A, 0xE6, 0x1A, 0x6C, 0xFD, 0xBB,
+ 0x27, 0xC1, 0x73, 0xB1, 0x4E, 0xAC, 0x97, 0x1B,
+ 0x8B, 0xB2, 0x0A, 0x6A, 0x67, 0xA0, 0xA9, 0xDD,
+ 0x88, 0xF0, 0x55, 0x58, 0x10, 0x79, 0x9C, 0xC5,
+
+ 0xAF, 0x48, 0x98, 0xFF, 0xF1, 0xC9, 0x67, 0xB3,
+ 0x74, 0xA9, 0xAC, 0xF5, 0x17, 0x7D, 0x95, 0x53,
+ 0x6A, 0xDD, 0xD6, 0x44, 0x3B, 0x09, 0x32, 0x78,
+ 0x2E, 0xEC, 0x19, 0x33, 0xD8, 0x4C, 0xFD, 0xE6,
+ 0xCE, 0x4A, 0x08, 0x78, 0xB5, 0xE8, 0x90, 0x1B,
+ 0x32, 0x04, 0x51, 0xC1, 0x4A, 0x1A, 0x69, 0xA2,
+ 0x0A, 0x76, 0x86, 0x73, 0x4B, 0x4C, 0xF7, 0x62,
+ 0xF7, 0xD0, 0x2E, 0x91, 0x8B, 0x7C, 0xFA, 0x8F,
+ 0xC9, 0xBE, 0x49, 0x9B, 0x1C, 0x58, 0xF8, 0x14,
+ 0xD1, 0x07, 0x4A, 0x4D, 0xE4, 0xB3, 0x83, 0x0A,
+ 0xD3, 0xF9, 0xDD, 0xC1, 0x2F, 0x84, 0x15, 0x02,
+ 0xA8, 0xB7, 0xB8, 0x45, 0x05, 0x99, 0x71, 0xEE,
+ 0xC6, 0x3B, 0xC4, 0xC3, 0x6F, 0x10, 0x63, 0x17,
+ 0x11, 0xD0, 0x1F, 0x1C, 0x63, 0xB9, 0x3F, 0x3D,
+ 0x68, 0x0A, 0x39, 0x25, 0x95, 0xB9, 0x81, 0xA7,
+ 0x04, 0x64, 0x6B, 0x2E, 0x52, 0xD0, 0x56, 0x04,
+ 0x99, 0x4F, 0x1B, 0x8E, 0xB0, 0x29, 0xA5, 0x3C,
+ 0x17, 0x46, 0xEC, 0x36, 0xC2, 0xD0, 0xAD, 0x92,
+ 0xB7, 0x58, 0x70, 0x33, 0xA9, 0xA3, 0xD8, 0xB7,
+ 0xF1, 0x04, 0xA7, 0xFA, 0x9D, 0x2C, 0x6B, 0x5A,
+ 0x52, 0x89, 0xAC, 0xD0, 0x12, 0x44, 0x8F, 0x7E,
+ 0x97, 0xA1, 0x82, 0x82, 0xB2, 0xEA, 0x47, 0x60,
+ 0x9B, 0x22, 0x32, 0x74, 0x77, 0x62, 0xE3, 0x46,
+ 0xF5, 0x55, 0x79, 0xEF, 0x9D, 0xB0, 0x2A, 0xC8,
+ 0x10, 0x2E, 0x7B, 0x3F, 0x00, 0xE8, 0x04, 0xA0,
+ 0x7E, 0x7F, 0x34, 0xB2, 0x35, 0x0E, 0x3A, 0x2F,
+ 0x65,
+
+ 0x0C, 0x94, 0x90, 0x76, 0x67, 0xAB, 0xE0, 0x58,
+ 0x2E, 0x22, 0xF4, 0x48, 0xE7, 0x3E, 0x44, 0xB6,
+ 0x6D, 0xD4, 0xBD, 0x46, 0xEB, 0x9E, 0x01, 0xF9,
+ 0xB3, 0x06, 0x6F, 0xBA, 0xEE, 0x06, 0x1F, 0xB9,
+ 0x22, 0xE3, 0x49, 0x27, 0x80, 0x86, 0xB5, 0x38,
+ 0x47, 0x77, 0x14, 0x68, 0x0B, 0xF2, 0x6C, 0x9A,
+ 0xF1, 0x1F, 0x20, 0xED, 0x86, 0xF9, 0xEE, 0x04,
+ 0x92, 0xBC, 0xAB, 0xB8, 0x6B, 0x4A, 0x9D, 0x63,
+ 0xEB, 0x1B, 0x69, 0x18, 0x3D, 0x81, 0x4D, 0x16,
+ 0x68, 0x63, 0xF1, 0x96, 0x96, 0x0B, 0x51, 0x66,
+ 0x93, 0xFE, 0x49, 0xEA, 0xF6, 0x55, 0x8A, 0x2A,
+ 0xD7, 0x2E, 0xD0, 0x2D, 0xBF, 0x85, 0xD5, 0x97,
+ 0x9D, 0x8D, 0x2D, 0xD3, 0xB3, 0x62, 0x61, 0xB6,
+ 0x3B, 0x7B, 0xD1, 0x17, 0xB3, 0xB4, 0x94, 0x2D,
+ 0xEC, 0x76, 0xD1, 0x39, 0x75, 0x39, 0xFA, 0xAA,
+ 0x5B, 0x47, 0x0D, 0x9F, 0xBC, 0xEC, 0x12, 0x4F,
+ 0x76, 0x7C, 0xCB, 0xAD, 0x19, 0x80, 0xCF, 0x65,
+ 0x7F, 0x1E, 0x64, 0x2D, 0xE7, 0xF1, 0x4B, 0x22,
+ 0x9D, 0xEE, 0x46, 0x48, 0xBA, 0x54, 0x32, 0x5D,
+ 0x33, 0xE0, 0x81, 0xF6, 0x9C, 0x2F, 0x1C, 0xBC,
+ 0x17, 0xCA, 0x34, 0x0C, 0x9A, 0xEF, 0x27, 0x8E,
+ 0x19, 0xD8, 0x8C, 0xC4, 0xED, 0x0C, 0x88, 0xBA,
+ 0x60, 0x8B, 0xCF, 0x84, 0xB8, 0xF0, 0x25, 0x8C,
+ 0x9E, 0xEA, 0x00, 0xE0, 0xB6, 0xC1, 0xAA, 0x02,
+ 0x51, 0xD9, 0xFF, 0xDA, 0x87, 0x9D, 0x62, 0xB1,
+ 0xD1, 0x52, 0x7D, 0xE8, 0xB1, 0xC2, 0x45, 0x7D,
+ 0x4D, 0xF8,
+
+ 0x20, 0xC9, 0xAD, 0x20, 0xED, 0x26, 0x96, 0x8F,
+ 0xF9, 0xEA, 0xD1, 0x3C, 0x54, 0xA2, 0x45, 0xAF,
+ 0x13, 0x85, 0x90, 0x43, 0xC3, 0xFD, 0x90, 0xBA,
+ 0x19, 0xAF, 0xB3, 0x6F, 0x3E, 0xD7, 0x01, 0xB3,
+ 0xCD, 0x1F, 0xAC, 0x35, 0x48, 0x29, 0x7E, 0xE3,
+ 0x7B, 0x5F, 0x2A, 0x48, 0x86, 0x27, 0x43, 0xAA,
+ 0x9C, 0x30, 0x6A, 0x4B, 0x13, 0x77, 0x2D, 0xE5,
+ 0xB4, 0xB2, 0x66, 0x82, 0xC0, 0x4E, 0xDE, 0x81,
+ 0x18, 0x9E, 0x4A, 0xC4, 0x0A, 0x20, 0x2E, 0x70,
+ 0xED, 0x7D, 0x48, 0x28, 0xF8, 0xE4, 0x68, 0x01,
+ 0xEF, 0x54, 0x43, 0x42, 0x3A, 0xA8, 0x65, 0xC6,
+ 0xF5, 0x94, 0x19, 0x8A, 0x23, 0x75, 0xBD, 0x08,
+ 0xAE, 0xA4, 0x78, 0x42, 0xD1, 0xF4, 0xF0, 0xA3,
+ 0x5A, 0x21, 0x74, 0x1B, 0x90, 0xD8, 0x05, 0x99,
+ 0xA7, 0x22, 0x7C, 0x79, 0xE9, 0x7D, 0xFF, 0xB2,
+ 0x1F, 0x04, 0x37, 0xAE, 0xFA, 0xD5, 0x93, 0x97,
+ 0x32, 0x7E, 0xFD, 0xBB, 0xAC, 0x6E, 0x96, 0xA5,
+ 0x4F, 0xB4, 0x89, 0x21, 0xB1, 0x3F, 0xB2, 0x3D,
+ 0xFA, 0x08, 0xCE, 0xED, 0x70, 0x23, 0xAF, 0x75,
+ 0x22, 0xDE, 0x2E, 0x12, 0x37, 0xE4, 0xB9, 0x92,
+ 0xA2, 0xB0, 0x4D, 0x56, 0xDE, 0x5E, 0xD3, 0x7F,
+ 0xBF, 0xBD, 0x5E, 0x6F, 0x4A, 0xBA, 0xC3, 0x27,
+ 0x22, 0x19, 0xA3, 0x4E, 0x90, 0x2E, 0x72, 0x2E,
+ 0xEB, 0x6B, 0x48, 0xD5, 0xC6, 0x00, 0x94, 0x56,
+ 0x29, 0x74, 0x13, 0x0B, 0x85, 0xCF, 0xE5, 0x51,
+ 0x83, 0xB5, 0x20, 0x49, 0xF0, 0xC6, 0x08, 0xEE,
+ 0x18, 0x26, 0x19,
+
+ 0x74, 0x41, 0x6D, 0x4E, 0x6C, 0x5E, 0x82, 0xB9,
+ 0xA6, 0x6E, 0x53, 0x6C, 0xEF, 0x7E, 0x43, 0x36,
+ 0x6A, 0xAA, 0x94, 0x99, 0xAA, 0x92, 0x44, 0xE6,
+ 0x41, 0x1D, 0x09, 0xE6, 0x5D, 0xF5, 0x8D, 0xCF,
+ 0x34, 0xE3, 0xAC, 0x10, 0x0B, 0x5D, 0xC1, 0x59,
+ 0xB7, 0x60, 0x6C, 0xCB, 0x75, 0x67, 0x85, 0x40,
+ 0xB8, 0x06, 0x54, 0xE0, 0xB7, 0xB9, 0x4E, 0x4A,
+ 0x52, 0xD0, 0x39, 0x9F, 0x2C, 0x01, 0xFE, 0xB2,
+ 0x09, 0x73, 0xA1, 0x6C, 0xD6, 0x0E, 0xB4, 0x8F,
+ 0x40, 0xA2, 0x15, 0x12, 0x88, 0x3D, 0x65, 0x49,
+ 0x0C, 0xE1, 0xF5, 0x95, 0xF4, 0xC0, 0xF2, 0x63,
+ 0x5F, 0xF6, 0x1B, 0xF2, 0x30, 0xC8, 0x5B, 0xE9,
+ 0xC0, 0x84, 0x0C, 0x6E, 0xDF, 0xC4, 0x19, 0xB9,
+ 0xCE, 0xA6, 0x49, 0xA5, 0x64, 0xE9, 0x66, 0xC3,
+ 0x6C, 0xE5, 0x93, 0x76, 0xAC, 0x59, 0x65, 0x0E,
+ 0xE6, 0xF5, 0x80, 0xCE, 0x1C, 0x72, 0x9A, 0x53,
+ 0xB0, 0xC7, 0xB6, 0x11, 0x65, 0xDE, 0xEC, 0x89,
+ 0x18, 0xD8, 0x05, 0x6E, 0x41, 0xD2, 0x31, 0xBD,
+ 0xDB, 0xE5, 0xEF, 0xF5, 0x76, 0x5C, 0xBD, 0x03,
+ 0x6D, 0x04, 0x00, 0x16, 0x64, 0x19, 0xFE, 0x4B,
+ 0x73, 0x9C, 0xDB, 0x31, 0x13, 0x50, 0xD6, 0xCB,
+ 0xE4, 0xFC, 0x73, 0x89, 0x0F, 0x50, 0x31, 0xBF,
+ 0x0E, 0xAB, 0xD8, 0xF2, 0x9C, 0xB8, 0x04, 0x88,
+ 0xAD, 0xE3, 0x9F, 0xDA, 0x0D, 0xE3, 0x5B, 0x34,
+ 0x94, 0xCB, 0x50, 0x61, 0xA4, 0x01, 0x03, 0xFA,
+ 0x4D, 0x85, 0xE4, 0x29, 0xFC, 0x11, 0x77, 0x97,
+ 0x75, 0x6D, 0xF3, 0xC1,
+
+ 0x16, 0x34, 0x6D, 0x2E, 0x36, 0x03, 0xC4, 0x4E,
+ 0xC5, 0xB4, 0xF8, 0xFA, 0x20, 0x49, 0x81, 0x68,
+ 0x7E, 0xC8, 0xC2, 0x13, 0x18, 0x84, 0x0C, 0x84,
+ 0xE8, 0xBF, 0xD9, 0x0D, 0x1B, 0x9F, 0xF0, 0x1F,
+ 0x8D, 0x41, 0x56, 0x5F, 0xBB, 0x1A, 0x21, 0x5F,
+ 0x0B, 0x7E, 0x79, 0xFC, 0x7C, 0x72, 0xD5, 0x80,
+ 0x64, 0x8A, 0xFD, 0xC5, 0xF9, 0xDC, 0x61, 0x27,
+ 0x75, 0x65, 0x0A, 0x2C, 0x2A, 0x4C, 0xE9, 0x7A,
+ 0x3A, 0xFA, 0x1E, 0xE6, 0x2A, 0x31, 0xFD, 0xD1,
+ 0xA0, 0xD8, 0xBF, 0xAB, 0x40, 0x61, 0x87, 0x9F,
+ 0xA8, 0x65, 0x18, 0x7C, 0x87, 0xEE, 0xA2, 0x93,
+ 0xC2, 0xE4, 0xED, 0xEF, 0x5C, 0x3D, 0x09, 0xC8,
+ 0xD7, 0x75, 0x76, 0xF2, 0x1A, 0x9E, 0x19, 0xB8,
+ 0x44, 0xE8, 0xBE, 0x4F, 0x71, 0xD2, 0xEF, 0x0A,
+ 0x83, 0x1C, 0xFC, 0xA5, 0x6F, 0x43, 0x0A, 0x1D,
+ 0xDA, 0xD7, 0x4D, 0x14, 0xE3, 0x5C, 0x32, 0x74,
+ 0x45, 0x19, 0xC4, 0xF4, 0x3D, 0x5A, 0x6E, 0xEC,
+ 0x5E, 0x54, 0xF1, 0xB3, 0xF1, 0x4B, 0x05, 0x52,
+ 0x92, 0x41, 0x49, 0x27, 0x18, 0x40, 0x38, 0x4E,
+ 0x0A, 0x7D, 0xD1, 0x31, 0x0A, 0xC8, 0x82, 0x60,
+ 0x5A, 0xBE, 0x4A, 0x5A, 0xAE, 0xBE, 0x86, 0x7D,
+ 0x2B, 0x27, 0x07, 0x2C, 0xFA, 0x65, 0xB0, 0x73,
+ 0x50, 0x68, 0x58, 0x36, 0x50, 0x74, 0x61, 0x57,
+ 0xAB, 0xF4, 0xE8, 0xCD, 0xEE, 0xBB, 0x29, 0x68,
+ 0x0E, 0x6C, 0x38, 0x0E, 0x0C, 0xDC, 0x79, 0x12,
+ 0xC7, 0xF4, 0x25, 0x74, 0x66, 0xD6, 0xC1, 0xF6,
+ 0xF0, 0xF6, 0x1D, 0x27, 0xA1,
+
+ 0xFA, 0x0C, 0xB5, 0xEE, 0x97, 0x04, 0x06, 0xF8,
+ 0x04, 0xE8, 0xBF, 0x1C, 0x3D, 0x19, 0x5A, 0x1C,
+ 0x04, 0xBC, 0x6F, 0x76, 0x50, 0x3D, 0x0C, 0xE7,
+ 0xCE, 0xE5, 0xDE, 0x6F, 0xA1, 0xE6, 0xA3, 0xE4,
+ 0x3C, 0xC6, 0x17, 0xBF, 0xDC, 0xDF, 0x56, 0xFC,
+ 0x63, 0xE9, 0x9F, 0x57, 0x0C, 0xF0, 0xA8, 0x19,
+ 0x1B, 0x8A, 0x33, 0xA3, 0xBF, 0xA8, 0xCD, 0xC4,
+ 0x24, 0x71, 0xA2, 0x4D, 0x2D, 0xF4, 0x3E, 0xB7,
+ 0xF9, 0xAD, 0x3B, 0xA9, 0xDF, 0xCF, 0x81, 0xBD,
+ 0x9A, 0x5A, 0x45, 0xC0, 0x94, 0xA2, 0xAF, 0x9A,
+ 0x86, 0xF6, 0xBF, 0x3B, 0x99, 0xDB, 0x1E, 0x41,
+ 0xFD, 0xA5, 0x57, 0xB3, 0x2E, 0x7B, 0x73, 0x4F,
+ 0x6A, 0xBF, 0xAD, 0x5F, 0x87, 0xFC, 0xA7, 0xEC,
+ 0xC9, 0xD6, 0x70, 0xDA, 0xED, 0x75, 0x84, 0x50,
+ 0x61, 0x7C, 0x73, 0x18, 0x8D, 0x7B, 0xF2, 0x47,
+ 0x85, 0x75, 0x0A, 0x19, 0xBF, 0xFE, 0x3B, 0x81,
+ 0x81, 0x15, 0x57, 0xD8, 0xE7, 0x13, 0xD6, 0xF6,
+ 0x0D, 0x49, 0xB9, 0x71, 0x23, 0x51, 0x3F, 0x6A,
+ 0x50, 0x70, 0xB6, 0x42, 0x18, 0xE9, 0xD9, 0xF5,
+ 0xEF, 0x60, 0x15, 0xE3, 0x73, 0xCD, 0x49, 0x09,
+ 0x4A, 0x87, 0x05, 0x5D, 0x45, 0xE1, 0x40, 0xAC,
+ 0x6E, 0xA0, 0xD0, 0x1C, 0xD4, 0xFE, 0x76, 0xE4,
+ 0xD8, 0x4E, 0x3E, 0x93, 0xC9, 0xC8, 0xC7, 0x4A,
+ 0x49, 0x8E, 0x79, 0x46, 0x5D, 0xB0, 0xEB, 0xDC,
+ 0x46, 0x88, 0x25, 0x5B, 0xE4, 0xE2, 0x0E, 0x0C,
+ 0xC9, 0xD3, 0xA2, 0x79, 0x1A, 0xF2, 0x94, 0xF2,
+ 0xC2, 0xE2, 0x98, 0x6E, 0x99, 0x87,
+
+ 0xDE, 0xEE, 0x45, 0x68, 0x9D, 0xC8, 0x03, 0xC0,
+ 0x02, 0x41, 0x3D, 0x9F, 0x33, 0x70, 0x73, 0x62,
+ 0x96, 0x25, 0x02, 0xF4, 0x74, 0x5D, 0xE2, 0xF1,
+ 0x67, 0xF2, 0xFD, 0xE1, 0x65, 0x47, 0x33, 0x6D,
+ 0xF4, 0x86, 0x11, 0x7C, 0xD0, 0x48, 0x02, 0x7C,
+ 0xA7, 0x26, 0x85, 0x27, 0xBE, 0x13, 0x96, 0x85,
+ 0x40, 0x1F, 0x6A, 0xB0, 0x0D, 0x8E, 0xD2, 0x02,
+ 0xD7, 0x03, 0xFD, 0x45, 0xC8, 0x08, 0xED, 0x3E,
+ 0x32, 0x04, 0x30, 0x48, 0x63, 0xA3, 0x65, 0x8C,
+ 0x11, 0x9D, 0x7B, 0x65, 0xE9, 0x02, 0x37, 0xF3,
+ 0x9D, 0x0B, 0x5E, 0xAD, 0x9D, 0xFF, 0x7D, 0x56,
+ 0x3D, 0x50, 0x74, 0x37, 0xAD, 0x39, 0x06, 0x85,
+ 0x10, 0xC5, 0x69, 0x37, 0x57, 0x3C, 0x4F, 0xE8,
+ 0x4A, 0xAC, 0x1D, 0x06, 0xDA, 0x62, 0xB3, 0x3E,
+ 0x0B, 0xB0, 0xE4, 0x1F, 0x3F, 0x2F, 0x29, 0x88,
+ 0x14, 0xC1, 0xAE, 0xD1, 0x62, 0x89, 0xB7, 0xC5,
+ 0x51, 0x72, 0xFE, 0xE3, 0xDF, 0x56, 0x9E, 0xDB,
+ 0x37, 0xE4, 0x64, 0xAC, 0x99, 0x08, 0xF7, 0x87,
+ 0xFA, 0xCE, 0x5B, 0xF3, 0xCD, 0x21, 0xF6, 0x8A,
+ 0xED, 0xA3, 0x7B, 0xEC, 0x3F, 0x30, 0x14, 0x3D,
+ 0x00, 0xD4, 0x40, 0xBE, 0x35, 0x36, 0x89, 0xCF,
+ 0x29, 0xDA, 0x13, 0xE8, 0x69, 0x0D, 0xDE, 0xE8,
+ 0x05, 0x22, 0x0D, 0x02, 0x18, 0xDB, 0x12, 0xAC,
+ 0x01, 0x12, 0xD0, 0xEF, 0xD2, 0x82, 0x21, 0xC9,
+ 0xF7, 0x52, 0x94, 0x98, 0x0E, 0xE7, 0xCB, 0x9C,
+ 0x3F, 0xD1, 0x0D, 0xA6, 0x0C, 0x53, 0x60, 0x8B,
+ 0x13, 0x3F, 0x77, 0xD5, 0xDC, 0xC5, 0xE2,
+
+ 0x7D, 0x3B, 0xAE, 0x67, 0x64, 0x19, 0xC8, 0x66,
+ 0xF1, 0x0F, 0x31, 0xAD, 0x43, 0x35, 0xD4, 0x44,
+ 0x2C, 0xA5, 0x5D, 0x76, 0x78, 0x70, 0x4C, 0x2F,
+ 0x71, 0x11, 0xB9, 0xF3, 0x69, 0x16, 0xFA, 0x09,
+ 0x42, 0xE7, 0x6C, 0x09, 0x2E, 0xDA, 0xEB, 0x9A,
+ 0x53, 0x82, 0x1D, 0x31, 0x3E, 0x3E, 0xD8, 0x48,
+ 0xEA, 0x86, 0xE8, 0x76, 0x8E, 0xC6, 0xA7, 0xEA,
+ 0xBB, 0x58, 0x7D, 0xB7, 0x39, 0x76, 0xEC, 0xE6,
+ 0x35, 0x19, 0xAA, 0xFA, 0x6E, 0x98, 0x2C, 0x38,
+ 0xC2, 0xA2, 0x0E, 0x36, 0xA9, 0x4F, 0x88, 0xDA,
+ 0x6E, 0x3D, 0x1C, 0xFB, 0x25, 0xF5, 0x96, 0x1E,
+ 0x18, 0xBE, 0xEB, 0x0A, 0x48, 0xB8, 0x5A, 0x42,
+ 0xD3, 0x77, 0xEB, 0xD1, 0x06, 0x93, 0x4D, 0x56,
+ 0xB0, 0x60, 0xAA, 0x72, 0x8B, 0xC4, 0x29, 0x2E,
+ 0xE5, 0x36, 0x53, 0x46, 0xA3, 0x4F, 0x27, 0xED,
+ 0xED, 0x0A, 0x19, 0xCC, 0xF1, 0x1C, 0xBB, 0x0C,
+ 0x43, 0x2C, 0x6E, 0x40, 0xCF, 0x0F, 0x58, 0x23,
+ 0xC0, 0xE1, 0x5F, 0x2A, 0x63, 0x06, 0xD0, 0x91,
+ 0x97, 0x9C, 0x16, 0x0E, 0x0A, 0xE6, 0xAF, 0x1D,
+ 0x7C, 0x07, 0xD6, 0xC4, 0x64, 0x01, 0xB9, 0xE4,
+ 0x6D, 0x75, 0x92, 0x4F, 0x35, 0x1B, 0x4C, 0x37,
+ 0xCE, 0x05, 0x88, 0x06, 0x08, 0x1C, 0xD6, 0x75,
+ 0xE2, 0x07, 0x2E, 0x54, 0x58, 0xA1, 0x00, 0x39,
+ 0xA4, 0x80, 0xBF, 0xB2, 0x1F, 0xC4, 0x69, 0xC1,
+ 0x3D, 0x4B, 0xFE, 0x7F, 0x20, 0x1F, 0x49, 0x8B,
+ 0x08, 0xC6, 0x33, 0x86, 0xEB, 0x7B, 0x3E, 0x16,
+ 0xDE, 0xE3, 0x34, 0xD8, 0x66, 0x04, 0x55, 0xBA,
+
+ 0xBE, 0x42, 0xC4, 0xEA, 0xAB, 0x31, 0xF5, 0x2E,
+ 0xF3, 0xF6, 0xBC, 0x86, 0xB6, 0xA4, 0x48, 0x74,
+ 0x15, 0xE9, 0xA7, 0x65, 0xE6, 0xDA, 0xF0, 0x94,
+ 0x5F, 0x1F, 0xC4, 0xCA, 0xD3, 0xFE, 0x66, 0x78,
+ 0x03, 0xE3, 0xBE, 0x9D, 0xE8, 0xAC, 0x45, 0x29,
+ 0xFA, 0x59, 0xE0, 0xBA, 0xD0, 0xAC, 0x62, 0x9A,
+ 0xA6, 0x6F, 0x6C, 0x5B, 0x0E, 0x86, 0xC8, 0x3E,
+ 0xD6, 0xE2, 0x84, 0x31, 0x79, 0xD1, 0xAF, 0xCB,
+ 0x78, 0x1D, 0xF5, 0x1D, 0x76, 0x72, 0xCC, 0xAA,
+ 0x7A, 0x22, 0x35, 0xBD, 0x3A, 0x26, 0x7B, 0x2B,
+ 0x08, 0xD8, 0x27, 0x26, 0x07, 0xA2, 0xAA, 0x6E,
+ 0x30, 0x8C, 0x38, 0x70, 0x40, 0x3C, 0x61, 0x9F,
+ 0x5C, 0x57, 0x72, 0x9B, 0x5B, 0x4C, 0x20, 0xB0,
+ 0x84, 0x1A, 0x85, 0x0C, 0xF3, 0x3E, 0x5B, 0x67,
+ 0x3D, 0xF2, 0xB4, 0x4F, 0xB1, 0xE6, 0x3D, 0xDC,
+ 0xF1, 0x3C, 0x49, 0x9A, 0x38, 0x95, 0x47, 0xF2,
+ 0xCA, 0x43, 0xB7, 0x0A, 0x80, 0x06, 0x9F, 0x06,
+ 0x4D, 0x02, 0x98, 0x44, 0xB0, 0x8B, 0x73, 0xC6,
+ 0x26, 0x5B, 0x14, 0xA1, 0xF6, 0x64, 0x37, 0xDE,
+ 0xF2, 0x22, 0x1A, 0x59, 0x85, 0xAE, 0xFD, 0x5A,
+ 0xE5, 0x71, 0xC8, 0xCF, 0x6C, 0xFA, 0x64, 0x27,
+ 0xFF, 0x55, 0x45, 0x88, 0xA4, 0x5A, 0x50, 0x82,
+ 0x47, 0x61, 0x4C, 0xE5, 0x43, 0x9A, 0xA9, 0x5A,
+ 0xCC, 0xA3, 0xCA, 0x1B, 0xA0, 0x28, 0x65, 0x6E,
+ 0xA4, 0xCE, 0xE2, 0x17, 0x41, 0x07, 0x50, 0x31,
+ 0x76, 0xCB, 0x61, 0x14, 0xE3, 0x50, 0x68, 0x2B,
+ 0xF2, 0x96, 0x6B, 0xCF, 0xFE, 0xF7, 0x91, 0xD6,
+ 0x6F,
+
+ 0x55, 0x68, 0x17, 0x44, 0xA4, 0xAE, 0x0A, 0xBE,
+ 0xB6, 0xF4, 0x72, 0xAA, 0x55, 0x65, 0x33, 0x22,
+ 0xC5, 0x86, 0x02, 0xC5, 0xB6, 0x13, 0x9B, 0x68,
+ 0x1E, 0xE8, 0xFD, 0x2D, 0xEB, 0x9E, 0xF2, 0x72,
+ 0xA3, 0xA7, 0x38, 0xC1, 0xDB, 0xDB, 0x72, 0x03,
+ 0xE9, 0x7E, 0x5B, 0x55, 0x12, 0x0A, 0x8B, 0x87,
+ 0x89, 0xA5, 0xB7, 0x93, 0xFA, 0x8E, 0x80, 0xAA,
+ 0xB5, 0xDC, 0xA4, 0x78, 0xD7, 0x76, 0x21, 0x7B,
+ 0xF0, 0x1B, 0x41, 0x89, 0x9F, 0x9C, 0x41, 0xE6,
+ 0xDE, 0x3A, 0xF6, 0x16, 0x66, 0xDF, 0xF1, 0xC9,
+ 0x59, 0x75, 0x18, 0xBE, 0xC5, 0xE3, 0x55, 0xA7,
+ 0x39, 0xF5, 0x04, 0xBA, 0x3A, 0x11, 0x53, 0x36,
+ 0x69, 0x58, 0x49, 0xC3, 0xB1, 0x4E, 0x65, 0x88,
+ 0xDA, 0x46, 0xB8, 0x79, 0x58, 0x32, 0x18, 0xBA,
+ 0x3E, 0x3C, 0x5C, 0x02, 0x34, 0xFD, 0xD1, 0x2F,
+ 0x32, 0xCA, 0x4D, 0x1A, 0x68, 0x3B, 0x73, 0xC6,
+ 0xD0, 0xA8, 0x71, 0x24, 0xA8, 0xD5, 0x82, 0x83,
+ 0x26, 0x99, 0xCA, 0x8E, 0xC9, 0x55, 0xF2, 0x92,
+ 0xD1, 0x95, 0x4E, 0xA7, 0x5F, 0x16, 0x56, 0xD7,
+ 0xEA, 0xCF, 0xD3, 0xC7, 0xD7, 0xEA, 0x79, 0xF4,
+ 0x12, 0xC4, 0x7E, 0x5B, 0xB3, 0x1D, 0xAE, 0x0A,
+ 0xFD, 0xE1, 0x9F, 0x27, 0xCC, 0x95, 0xC6, 0x03,
+ 0xFD, 0x2F, 0xD3, 0xC5, 0x4E, 0xEF, 0x42, 0x10,
+ 0xF4, 0x6B, 0x24, 0x78, 0x53, 0xC5, 0xE1, 0xB6,
+ 0xB7, 0x80, 0xBD, 0xEB, 0x65, 0x5B, 0xA8, 0xE5,
+ 0x8E, 0xE5, 0x7F, 0x1E, 0x5B, 0x93, 0xA4, 0xDD,
+ 0xD5, 0xAB, 0xF2, 0x4A, 0x75, 0xE0, 0xAC, 0xC1,
+ 0x0C, 0x2D,
+
+ 0x3A, 0x63, 0xF3, 0x06, 0x48, 0xB8, 0x7A, 0x18,
+ 0x11, 0x6F, 0x96, 0x89, 0x2C, 0x01, 0x1F, 0x47,
+ 0x73, 0xF4, 0x9E, 0x28, 0x77, 0xE8, 0xCD, 0x57,
+ 0x36, 0x53, 0xB4, 0x33, 0x62, 0x83, 0x51, 0x7A,
+ 0x4A, 0x4D, 0xC3, 0xF7, 0x58, 0x19, 0x73, 0xB5,
+ 0xFF, 0x36, 0x3E, 0x63, 0xB0, 0xD1, 0x12, 0x07,
+ 0xB9, 0x17, 0xF1, 0xC6, 0x78, 0x79, 0xA1, 0x2D,
+ 0x4F, 0x00, 0xAF, 0xCD, 0xA3, 0x73, 0x09, 0xDD,
+ 0x9C, 0x3D, 0x8E, 0x6B, 0x2B, 0xA5, 0xF5, 0x91,
+ 0x1C, 0x2B, 0xFE, 0xB8, 0xE5, 0x6E, 0xA5, 0x9D,
+ 0x5D, 0x5C, 0x6A, 0xF2, 0xA1, 0x7E, 0x82, 0xB0,
+ 0x47, 0xB5, 0x53, 0xE4, 0x49, 0x00, 0x5B, 0x60,
+ 0x5C, 0x94, 0x6E, 0xD1, 0xDE, 0x27, 0x7C, 0xC2,
+ 0xA2, 0xFF, 0xB4, 0xAF, 0x5F, 0x52, 0x0F, 0x5B,
+ 0x3B, 0xA5, 0x48, 0x93, 0x90, 0x97, 0x30, 0x10,
+ 0x30, 0x96, 0x84, 0x68, 0x8D, 0xB4, 0x47, 0x9E,
+ 0x77, 0x23, 0x2A, 0x96, 0xA9, 0x29, 0x2E, 0xBC,
+ 0x40, 0x59, 0x92, 0xE4, 0x55, 0xD7, 0x30, 0x2E,
+ 0x62, 0x15, 0xA6, 0xEA, 0x77, 0x5D, 0x2C, 0x1C,
+ 0x10, 0xF5, 0x8A, 0x43, 0x2B, 0x72, 0xC3, 0xD0,
+ 0x9E, 0xB9, 0x80, 0x4C, 0x8D, 0xCD, 0x5B, 0xB5,
+ 0xAD, 0xF6, 0x44, 0xDD, 0x9D, 0x37, 0x8E, 0x28,
+ 0xF1, 0xB5, 0xCE, 0xF2, 0xDD, 0x35, 0x6F, 0x63,
+ 0xB3, 0x32, 0xAC, 0x13, 0x4B, 0xC9, 0x67, 0x58,
+ 0x63, 0x2F, 0xB4, 0x23, 0x0C, 0xA3, 0x4F, 0xF8,
+ 0xB6, 0x52, 0xE7, 0xD1, 0xA7, 0x0D, 0x0D, 0x5B,
+ 0x66, 0x1D, 0x77, 0x82, 0xCA, 0xE5, 0x11, 0x62,
+ 0xF4, 0xA9, 0x95,
+
+ 0xE7, 0x1E, 0xF9, 0x44, 0xCD, 0x9F, 0xB5, 0xC5,
+ 0x80, 0xDC, 0x78, 0xA9, 0x4E, 0xAB, 0xD3, 0x1D,
+ 0xA9, 0xC6, 0xCC, 0x67, 0x49, 0xC2, 0x9C, 0x99,
+ 0x60, 0x86, 0xBA, 0x95, 0xDD, 0x10, 0x02, 0x37,
+ 0xE8, 0x2B, 0xF9, 0x2B, 0xB3, 0x97, 0x44, 0xDA,
+ 0xEF, 0x65, 0xB6, 0xB2, 0x0D, 0xA4, 0xAB, 0xFE,
+ 0xD7, 0x19, 0x07, 0xBD, 0x5B, 0xCC, 0x56, 0x78,
+ 0x90, 0xBA, 0x9C, 0x85, 0x7B, 0xD7, 0xDE, 0xD2,
+ 0x07, 0x29, 0xB2, 0x82, 0xF1, 0x37, 0x7A, 0x87,
+ 0xB9, 0x04, 0xF6, 0xE2, 0xC9, 0xF7, 0xDD, 0x1D,
+ 0xA4, 0x25, 0xB0, 0x18, 0x49, 0x72, 0x6F, 0x02,
+ 0xB1, 0x49, 0xB9, 0x15, 0xA6, 0x00, 0x87, 0x23,
+ 0x88, 0xED, 0xB7, 0xD5, 0xA2, 0x12, 0xC2, 0xA6,
+ 0xF3, 0x8A, 0x8C, 0x50, 0xE2, 0xC9, 0xBC, 0x62,
+ 0x50, 0xF8, 0x2C, 0xB1, 0x11, 0x00, 0x36, 0x79,
+ 0x13, 0x75, 0xFB, 0x87, 0xDA, 0x49, 0x59, 0x42,
+ 0x57, 0xDD, 0x7C, 0xE4, 0xFA, 0xD1, 0x5B, 0xF9,
+ 0xB5, 0xB8, 0x56, 0xB0, 0x98, 0xF9, 0x63, 0xB1,
+ 0x1B, 0xEC, 0xF7, 0x05, 0x4C, 0xBC, 0x32, 0x1C,
+ 0x59, 0xC8, 0x75, 0x7E, 0xBC, 0xAD, 0xCF, 0x32,
+ 0x1A, 0x3D, 0xAE, 0x1F, 0x27, 0x01, 0x85, 0x60,
+ 0xCB, 0xDE, 0xAB, 0x39, 0xFD, 0x1E, 0x45, 0x82,
+ 0x36, 0xC1, 0xC3, 0x69, 0xA7, 0xE4, 0x5B, 0x16,
+ 0x36, 0x5A, 0xD5, 0x20, 0x5E, 0x4D, 0x1C, 0xBA,
+ 0x6E, 0x28, 0x30, 0x66, 0xDA, 0x6C, 0x66, 0x42,
+ 0xD4, 0x9A, 0x98, 0x31, 0xF8, 0x11, 0x8A, 0xB5,
+ 0xF9, 0x9E, 0x96, 0xE9, 0x42, 0x0D, 0xDF, 0x28,
+ 0x2D, 0x03, 0xC6, 0xFF,
+
+ 0x05, 0x1F, 0xCE, 0x41, 0xE4, 0x8C, 0x74, 0x81,
+ 0x36, 0x78, 0x17, 0x9E, 0x28, 0xCC, 0xA0, 0xA8,
+ 0x03, 0x13, 0xEB, 0x8D, 0xD9, 0xF5, 0x75, 0x8C,
+ 0x58, 0x0B, 0xA5, 0x3F, 0xB5, 0x5D, 0x48, 0x94,
+ 0xA9, 0x7D, 0x61, 0x34, 0x5F, 0x07, 0xA2, 0x84,
+ 0x6A, 0xF9, 0x6C, 0xCB, 0x4C, 0x5D, 0x2D, 0xB2,
+ 0x05, 0x0B, 0x03, 0x61, 0x4A, 0x68, 0xB3, 0xA2,
+ 0x08, 0x33, 0x68, 0xB0, 0xD9, 0x95, 0x63, 0x98,
+ 0xBA, 0xF9, 0x70, 0x81, 0xDC, 0x34, 0xD2, 0xA3,
+ 0x5C, 0x5E, 0x85, 0x22, 0x8D, 0xEB, 0xEE, 0x81,
+ 0xEC, 0xEE, 0x43, 0xAC, 0x70, 0x93, 0x2C, 0xBC,
+ 0x66, 0x33, 0x37, 0xD9, 0xE1, 0x71, 0x2F, 0xD0,
+ 0x5A, 0xB8, 0x32, 0x8C, 0xE7, 0x98, 0x13, 0x8C,
+ 0x61, 0x94, 0x6C, 0xAA, 0x38, 0xCF, 0xAD, 0xF6,
+ 0xBE, 0x40, 0xA9, 0x6F, 0x02, 0xFA, 0x16, 0x5C,
+ 0x70, 0x2E, 0x55, 0xCC, 0x5F, 0x5A, 0xF7, 0x07,
+ 0x95, 0xB0, 0x18, 0xB7, 0xF0, 0x4A, 0xFA, 0xCD,
+ 0xB4, 0xA8, 0x92, 0x3F, 0x71, 0xED, 0x8F, 0x54,
+ 0xC0, 0x35, 0x1F, 0x2E, 0xC7, 0xF2, 0xBE, 0x4B,
+ 0x96, 0x4F, 0x05, 0xB7, 0x3E, 0x9E, 0x40, 0xA9,
+ 0x2A, 0xC7, 0x1C, 0x2D, 0x91, 0x5A, 0xBB, 0x31,
+ 0xB1, 0x4F, 0xE1, 0x3F, 0x34, 0x27, 0x4D, 0xAD,
+ 0x19, 0x34, 0xC5, 0x4F, 0x2C, 0x32, 0x24, 0x3E,
+ 0x9E, 0x50, 0x1F, 0xC2, 0x57, 0x63, 0xFF, 0x45,
+ 0xBE, 0x73, 0x72, 0xED, 0xE6, 0x01, 0x35, 0x33,
+ 0xCD, 0x14, 0xC2, 0xF4, 0xFB, 0xEF, 0x47, 0x55,
+ 0x3F, 0x4B, 0xD0, 0x05, 0xF0, 0x38, 0x2A, 0x37,
+ 0xAF, 0x02, 0xD9, 0x25, 0xDD,
+
+ 0x20, 0xCE, 0x9F, 0xBC, 0x8E, 0x72, 0x30, 0xBB,
+ 0xE1, 0xC8, 0x3C, 0x08, 0x89, 0x34, 0x73, 0x4C,
+ 0x8D, 0x0C, 0x00, 0x1E, 0xA4, 0xD4, 0xDA, 0x55,
+ 0x18, 0x8C, 0xF0, 0xA4, 0x2F, 0xE9, 0x06, 0x30,
+ 0xDE, 0x73, 0xDA, 0x14, 0xA8, 0x82, 0xC3, 0x94,
+ 0xAE, 0x12, 0xC5, 0x55, 0x5B, 0x15, 0x42, 0x75,
+ 0x7A, 0xC3, 0x79, 0x05, 0x09, 0x63, 0x9A, 0xC4,
+ 0xD4, 0xCA, 0x1D, 0x08, 0x75, 0x68, 0x78, 0x07,
+ 0x7D, 0xD2, 0x37, 0xEB, 0x8B, 0x25, 0xAC, 0xF4,
+ 0x90, 0x5F, 0x4A, 0x2D, 0xE4, 0x4F, 0x08, 0x3B,
+ 0x3D, 0xF3, 0x9F, 0xA4, 0x8E, 0xEE, 0xE6, 0x47,
+ 0x4F, 0x3A, 0x6D, 0xBC, 0xB7, 0xA9, 0x4C, 0x1D,
+ 0x82, 0x4E, 0x7A, 0x29, 0xC9, 0x01, 0xFF, 0xC6,
+ 0x6F, 0x63, 0x4C, 0xE3, 0x0A, 0x10, 0x3F, 0x07,
+ 0xB4, 0x3F, 0x71, 0x55, 0x8D, 0xE3, 0xEF, 0xFC,
+ 0x76, 0xF6, 0x0A, 0xC3, 0xE9, 0xA9, 0x28, 0x03,
+ 0xB0, 0xDF, 0x15, 0x0E, 0xD0, 0x68, 0x17, 0x7D,
+ 0xC7, 0xC2, 0x51, 0x1A, 0x0D, 0x24, 0x21, 0x21,
+ 0x45, 0xFF, 0xEA, 0x17, 0xFB, 0xBF, 0x59, 0x63,
+ 0x03, 0x4F, 0x62, 0xEF, 0x1C, 0xDA, 0xF5, 0x00,
+ 0x8F, 0x9D, 0x2B, 0x81, 0x62, 0x9F, 0xED, 0xA6,
+ 0x6D, 0xA0, 0x57, 0x16, 0x08, 0x9E, 0x07, 0xB9,
+ 0xF3, 0x8B, 0x78, 0xA8, 0x6E, 0x15, 0x53, 0x26,
+ 0xE5, 0x7A, 0xE4, 0xBA, 0x09, 0xC6, 0x25, 0x41,
+ 0x1A, 0x24, 0x9B, 0xE0, 0x16, 0x62, 0xCF, 0x67,
+ 0xB6, 0xA1, 0xEF, 0x8B, 0x4D, 0xCC, 0xC3, 0xB6,
+ 0xB6, 0x89, 0x6C, 0x79, 0x02, 0x56, 0x79, 0x87,
+ 0xF4, 0xA7, 0x4B, 0x1D, 0xBC, 0xC0,
+
+ 0x34, 0xF6, 0x75, 0xEA, 0x0F, 0x48, 0x36, 0xB3,
+ 0x59, 0x85, 0x62, 0x0F, 0xEF, 0x08, 0xA8, 0xEB,
+ 0x6F, 0x83, 0x96, 0x3D, 0xDA, 0x81, 0x49, 0xF3,
+ 0x9D, 0xBD, 0x99, 0x93, 0x3B, 0x86, 0xF3, 0x9F,
+ 0xEF, 0x0F, 0x16, 0x0F, 0xBD, 0x58, 0x11, 0x93,
+ 0x1E, 0xF2, 0xAB, 0x31, 0xB0, 0x2E, 0x8B, 0x3D,
+ 0x57, 0x97, 0x6F, 0x54, 0xA2, 0x75, 0x04, 0xBE,
+ 0x9E, 0xF2, 0x57, 0x23, 0xC7, 0x3C, 0x4A, 0x4B,
+ 0xF0, 0xBC, 0x61, 0x53, 0x88, 0xC5, 0x91, 0x34,
+ 0x58, 0xEE, 0x16, 0xA3, 0xB7, 0x68, 0xDE, 0x60,
+ 0x99, 0x50, 0xF6, 0x3B, 0x14, 0x55, 0xC0, 0xE7,
+ 0xEE, 0x34, 0xA4, 0x29, 0xED, 0xD5, 0x5E, 0x6A,
+ 0xD2, 0xAD, 0x09, 0xCD, 0x21, 0x63, 0x7D, 0xAD,
+ 0xCC, 0xB1, 0x15, 0xD4, 0x4A, 0x12, 0x7A, 0xD2,
+ 0xB5, 0xE3, 0x79, 0x7A, 0x88, 0xFE, 0x57, 0x77,
+ 0xB9, 0xE6, 0x08, 0xE4, 0xA4, 0x62, 0x7A, 0xED,
+ 0xBF, 0x4F, 0xC2, 0xD8, 0x66, 0x4A, 0x3D, 0xA8,
+ 0xEC, 0xC6, 0x1C, 0xE7, 0xAF, 0xC4, 0x2B, 0x3B,
+ 0xB5, 0x5D, 0xF0, 0x33, 0xBA, 0xF2, 0x61, 0x99,
+ 0x92, 0xCF, 0x34, 0x19, 0x99, 0x43, 0xF5, 0x9F,
+ 0xF6, 0x64, 0x5A, 0x40, 0x87, 0x53, 0x2D, 0x16,
+ 0x75, 0x68, 0x31, 0xAA, 0x61, 0xCF, 0x1F, 0xC3,
+ 0x32, 0x5B, 0x78, 0xFB, 0x8D, 0x67, 0x1F, 0x16,
+ 0x80, 0x3A, 0x7E, 0x05, 0x45, 0x7A, 0x5E, 0x43,
+ 0x0A, 0x2E, 0xE1, 0x22, 0xA8, 0x96, 0x79, 0xD5,
+ 0xC4, 0x2E, 0xE0, 0x1F, 0x43, 0x1B, 0x8D, 0xDC,
+ 0xBA, 0xCF, 0x7D, 0xF2, 0xD1, 0x70, 0xF6, 0x65,
+ 0x44, 0xCE, 0x2B, 0x08, 0x0D, 0x43, 0xC4,
+
+ 0xF1, 0x1E, 0x0E, 0xFC, 0x7A, 0x10, 0x39, 0x3A,
+ 0x1E, 0xAD, 0x9E, 0x81, 0xC9, 0x04, 0xDB, 0x02,
+ 0x15, 0xC4, 0x9F, 0x6F, 0xD8, 0xF4, 0xCE, 0x77,
+ 0x00, 0x46, 0xB9, 0x0C, 0xD1, 0x4B, 0x1D, 0x6C,
+ 0x44, 0xFA, 0x19, 0x09, 0xB6, 0xEB, 0x34, 0x4A,
+ 0xC2, 0xDF, 0xF3, 0xF2, 0xE7, 0x3A, 0xE3, 0x6C,
+ 0xD4, 0xAF, 0x22, 0xFF, 0x40, 0xBC, 0x5C, 0x4A,
+ 0xBA, 0x7E, 0x54, 0xB1, 0xDB, 0xDF, 0x02, 0x2D,
+ 0xC2, 0xAD, 0x7B, 0x3E, 0x4C, 0x8E, 0x42, 0x97,
+ 0xDA, 0x00, 0xAA, 0x9F, 0x6A, 0x33, 0xB1, 0xFF,
+ 0xBB, 0x5E, 0x5F, 0x10, 0xE6, 0xA0, 0xF3, 0x25,
+ 0x8B, 0xAC, 0x36, 0xCF, 0xB6, 0x4A, 0x4D, 0x12,
+ 0x77, 0xDA, 0x17, 0xC5, 0xD5, 0xD2, 0xCB, 0xA1,
+ 0x95, 0xBB, 0xF1, 0xC9, 0xD8, 0xD3, 0xC1, 0xCC,
+ 0x67, 0xCE, 0xAB, 0x2B, 0x6A, 0x69, 0x41, 0x7C,
+ 0x7A, 0x47, 0x25, 0xE8, 0x39, 0xDC, 0x29, 0x31,
+ 0x36, 0x20, 0xA0, 0x58, 0x2A, 0x1A, 0xF0, 0x22,
+ 0xB9, 0x04, 0x10, 0xDA, 0x42, 0x2A, 0x6E, 0x1F,
+ 0x78, 0x01, 0x7C, 0x05, 0xE3, 0x1B, 0xA1, 0xC3,
+ 0x1A, 0x26, 0xA6, 0xF6, 0xBF, 0x54, 0xE9, 0x45,
+ 0x7F, 0x87, 0x08, 0xB8, 0xAF, 0xF0, 0xF0, 0xB4,
+ 0x96, 0xA4, 0xE3, 0xC0, 0x6A, 0x0B, 0xF9, 0x49,
+ 0x89, 0x1B, 0x9E, 0x69, 0x42, 0xD8, 0x21, 0x57,
+ 0x20, 0xC3, 0x95, 0xE5, 0xC6, 0x98, 0x06, 0x5E,
+ 0x69, 0x1F, 0x14, 0x8E, 0x9F, 0xF8, 0x58, 0x7C,
+ 0xEE, 0x13, 0xC7, 0x96, 0xC1, 0xE7, 0x71, 0x88,
+ 0x96, 0x54, 0xF9, 0xA7, 0xD6, 0x56, 0x7B, 0x8C,
+ 0xA5, 0x44, 0x42, 0xD3, 0x6B, 0x2E, 0x2E, 0x03,
+
+ 0x7D, 0x39, 0xA9, 0xFF, 0x6A, 0x3D, 0x14, 0x95,
+ 0x1C, 0xB6, 0xD8, 0x13, 0x4E, 0x41, 0xF5, 0xD5,
+ 0x3F, 0x0F, 0xEC, 0x55, 0x1E, 0xAC, 0x95, 0x79,
+ 0x28, 0x5D, 0xBD, 0xBE, 0xC4, 0x7D, 0x31, 0x1F,
+ 0x64, 0x11, 0x9D, 0x0B, 0x8F, 0x06, 0xAB, 0x23,
+ 0x2D, 0x8D, 0xC4, 0x10, 0xE7, 0x20, 0x95, 0x60,
+ 0x76, 0xFC, 0xFA, 0xE3, 0x64, 0xC3, 0x67, 0x32,
+ 0xFA, 0x3D, 0x5D, 0x8F, 0xEA, 0xE3, 0x4F, 0x95,
+ 0x0A, 0x37, 0x4A, 0x30, 0x98, 0x93, 0x76, 0x20,
+ 0x7F, 0xB7, 0xA9, 0xE0, 0x6C, 0x42, 0xE7, 0xF8,
+ 0x57, 0xC8, 0xBE, 0xD3, 0x7A, 0x1E, 0xBE, 0xF8,
+ 0x30, 0x8C, 0x29, 0x95, 0x71, 0x29, 0xFD, 0x79,
+ 0x0E, 0x1D, 0xDD, 0x4B, 0x41, 0xE9, 0x5F, 0x7E,
+ 0xF5, 0x4C, 0x7F, 0xA2, 0x10, 0x06, 0x57, 0x86,
+ 0xAB, 0x10, 0xBF, 0x5A, 0xFE, 0xA2, 0x5F, 0xE8,
+ 0x70, 0x8F, 0xCC, 0x00, 0xD9, 0x86, 0x86, 0x2C,
+ 0x31, 0x2E, 0xF9, 0xAD, 0x56, 0x0C, 0xE9, 0xB9,
+ 0x42, 0x39, 0x3B, 0x0D, 0x47, 0x60, 0x6F, 0xF9,
+ 0xFB, 0xE8, 0xBE, 0xFC, 0x7D, 0x0B, 0xA3, 0xEC,
+ 0x09, 0x6E, 0x0E, 0x0B, 0x6D, 0xEC, 0x60, 0x17,
+ 0xE9, 0x34, 0x65, 0x6F, 0xA4, 0x84, 0x61, 0x13,
+ 0xB2, 0xA6, 0xD3, 0x56, 0x06, 0xD9, 0xAE, 0x9A,
+ 0x57, 0x78, 0x93, 0xF2, 0x86, 0xA5, 0x39, 0x27,
+ 0x20, 0x36, 0x7A, 0xE7, 0xDE, 0x63, 0x02, 0x90,
+ 0x52, 0x3B, 0x7D, 0x32, 0x24, 0xFA, 0x77, 0x3A,
+ 0xFF, 0x6D, 0x6D, 0x38, 0xB1, 0xDC, 0x78, 0x06,
+ 0x5A, 0xCE, 0x72, 0xE9, 0x72, 0x22, 0x72, 0x60,
+ 0x90, 0x25, 0x72, 0x00, 0x28, 0xA2, 0xC0, 0x4A,
+ 0x31,
+
+ 0xFE, 0xCE, 0x1F, 0x8E, 0xEF, 0xB9, 0x81, 0xD1,
+ 0x1D, 0x7F, 0x88, 0x64, 0xF5, 0x96, 0xE5, 0xD0,
+ 0xCD, 0x3E, 0xBE, 0x2D, 0x39, 0x22, 0x61, 0xBA,
+ 0xC9, 0x91, 0xA1, 0xF6, 0x6E, 0x5F, 0x7E, 0x2A,
+ 0x90, 0xD0, 0x26, 0xB7, 0x6D, 0x1B, 0xAE, 0xE2,
+ 0x54, 0xDE, 0x79, 0xF8, 0x39, 0x1E, 0xA0, 0xFC,
+ 0x65, 0xE1, 0x45, 0x22, 0x7A, 0x1A, 0x06, 0x0A,
+ 0xBB, 0x59, 0x41, 0xF5, 0xCF, 0xC0, 0x4C, 0x76,
+ 0xB7, 0x98, 0xF8, 0x2F, 0x32, 0xE6, 0x5B, 0xC3,
+ 0x70, 0xF3, 0xF5, 0x18, 0xC5, 0x0B, 0xAF, 0x82,
+ 0x4A, 0x17, 0xEF, 0xA5, 0x96, 0xE2, 0x20, 0xBA,
+ 0xE5, 0x23, 0x55, 0xD2, 0x85, 0xA3, 0x1C, 0x1E,
+ 0x46, 0xDA, 0xCF, 0xD3, 0xAC, 0x56, 0xF6, 0x94,
+ 0xFE, 0x14, 0xBB, 0x15, 0xD6, 0xA0, 0xF3, 0x5B,
+ 0x5C, 0x62, 0xA3, 0xEC, 0xF8, 0x23, 0x75, 0x62,
+ 0x5D, 0xB9, 0x47, 0x46, 0x25, 0xF1, 0x9E, 0x88,
+ 0xC0, 0xF7, 0x5A, 0xC2, 0xA7, 0x97, 0xEA, 0xB1,
+ 0x35, 0x70, 0x02, 0x33, 0x29, 0xA9, 0xF9, 0x36,
+ 0xC8, 0xF0, 0x70, 0xCB, 0xD0, 0xD4, 0x07, 0x26,
+ 0xD6, 0x9C, 0x62, 0x37, 0xEB, 0xDD, 0xE1, 0x71,
+ 0x10, 0x49, 0x52, 0x86, 0x71, 0xC1, 0xB7, 0x78,
+ 0xE4, 0x85, 0xC2, 0x34, 0x3E, 0x83, 0xF2, 0xBE,
+ 0x31, 0x51, 0x65, 0xF4, 0x42, 0xE4, 0x66, 0x85,
+ 0xE8, 0xEF, 0xDD, 0xD9, 0xE0, 0x41, 0x3E, 0x25,
+ 0xF2, 0x9D, 0xCA, 0x48, 0xF3, 0x55, 0x99, 0x83,
+ 0xD6, 0xF3, 0x96, 0x37, 0xF5, 0x18, 0x90, 0x2E,
+ 0xA4, 0xA7, 0xE1, 0x08, 0x89, 0xFA, 0x54, 0x22,
+ 0xE8, 0x1D, 0x8E, 0xFE, 0x94, 0xED, 0x86, 0xF2,
+ 0x21, 0xE4,
+
+ 0xE1, 0x07, 0xBB, 0xC9, 0x51, 0x1C, 0xA7, 0x07,
+ 0xE9, 0x61, 0x25, 0xB4, 0x69, 0x8D, 0x72, 0xF1,
+ 0xF0, 0x12, 0xBB, 0x01, 0xD0, 0xCA, 0x4F, 0x29,
+ 0x42, 0x6B, 0x97, 0x7E, 0xC1, 0x8B, 0x1D, 0x9B,
+ 0x64, 0xD9, 0x21, 0x24, 0xF3, 0xE0, 0xEA, 0x72,
+ 0xD3, 0x5E, 0xEB, 0x71, 0x27, 0xEE, 0xEF, 0x09,
+ 0x3A, 0xDF, 0x73, 0x2E, 0xBE, 0x30, 0x57, 0xCD,
+ 0xEB, 0x49, 0x28, 0x83, 0x58, 0xB6, 0xBB, 0x91,
+ 0x90, 0xAC, 0x38, 0xBF, 0xC5, 0x6A, 0x6F, 0x6E,
+ 0x2F, 0xFF, 0x98, 0xD2, 0xFF, 0xE1, 0xB6, 0x5C,
+ 0x10, 0x3F, 0xBB, 0xA5, 0xDB, 0xC8, 0x56, 0x64,
+ 0x0D, 0xD6, 0xBE, 0xD2, 0x76, 0xF0, 0x33, 0xA0,
+ 0x37, 0xD1, 0xC6, 0xF1, 0x32, 0x96, 0x84, 0x17,
+ 0xE9, 0x4D, 0x37, 0x1B, 0x76, 0x60, 0x5F, 0xAA,
+ 0xD0, 0x70, 0xEF, 0xA7, 0x83, 0x48, 0xC6, 0xAE,
+ 0xB0, 0xCF, 0x6B, 0x72, 0x2D, 0x43, 0x7A, 0x7C,
+ 0x18, 0x25, 0x6B, 0xC7, 0x16, 0x60, 0x5C, 0x5D,
+ 0xF9, 0x1E, 0xE4, 0x0B, 0xAD, 0x7B, 0x06, 0x23,
+ 0xCA, 0xB8, 0x46, 0x05, 0xFC, 0x47, 0xBF, 0xCC,
+ 0xF7, 0x78, 0x9A, 0xB6, 0xDE, 0x12, 0xA0, 0x5D,
+ 0x1C, 0x1B, 0xF5, 0x36, 0x77, 0x9E, 0x8F, 0x95,
+ 0x7E, 0x3F, 0x5F, 0x82, 0xE7, 0xF5, 0x3D, 0xF6,
+ 0xEF, 0x13, 0x95, 0xB5, 0xEE, 0x3B, 0x1F, 0x0E,
+ 0x20, 0x02, 0xEA, 0x85, 0xFB, 0x09, 0x84, 0xCE,
+ 0x93, 0x8D, 0x48, 0x67, 0xCC, 0xA0, 0x98, 0x2E,
+ 0xFF, 0xD4, 0x5D, 0x45, 0x81, 0x0D, 0x43, 0xA5,
+ 0xD5, 0xC9, 0xD1, 0x4D, 0x5B, 0x3A, 0x9F, 0x4D,
+ 0x85, 0x8E, 0x95, 0x6A, 0xD7, 0x98, 0x85, 0x95,
+ 0x6F, 0x3E, 0x1E,
+
+ 0x8F, 0x79, 0x64, 0x19, 0x20, 0xB6, 0x73, 0xAD,
+ 0x05, 0xF9, 0x92, 0xB5, 0x64, 0xFD, 0x00, 0x8A,
+ 0xD1, 0x35, 0x86, 0xF9, 0x1B, 0x1C, 0x6C, 0x48,
+ 0x2A, 0x54, 0x07, 0xCD, 0x59, 0xD7, 0xC2, 0x1B,
+ 0xA5, 0xF6, 0x25, 0x80, 0xF2, 0xC7, 0x4D, 0xE6,
+ 0xC8, 0xB1, 0x6B, 0x02, 0x90, 0x19, 0x82, 0xCD,
+ 0xEB, 0x35, 0xC5, 0xB9, 0x9C, 0xE6, 0x18, 0xBF,
+ 0xD5, 0xFA, 0x16, 0x72, 0x5E, 0x41, 0x1B, 0x85,
+ 0xB3, 0xA6, 0x96, 0xA8, 0x3C, 0x84, 0x7A, 0xB9,
+ 0xCE, 0xA5, 0x18, 0xA8, 0xE5, 0x78, 0x9C, 0x1D,
+ 0x2D, 0x5F, 0x8C, 0x7C, 0x09, 0xF9, 0xE5, 0xFB,
+ 0xDD, 0x56, 0xD9, 0x95, 0x60, 0xB1, 0x12, 0xD6,
+ 0x86, 0x6C, 0x3B, 0xE8, 0x2C, 0x22, 0xE3, 0xAB,
+ 0xEF, 0xC5, 0x8E, 0x0A, 0x3F, 0x6E, 0x3A, 0x1B,
+ 0x5D, 0x39, 0x96, 0x1B, 0xC3, 0x8B, 0x59, 0x1C,
+ 0xC3, 0xE4, 0x10, 0xD7, 0x29, 0x43, 0x14, 0xEB,
+ 0x63, 0x88, 0x53, 0x6E, 0x44, 0x8F, 0xAD, 0x5A,
+ 0xDD, 0xF4, 0x8A, 0xD0, 0x20, 0x21, 0x02, 0x6B,
+ 0x81, 0x05, 0xB1, 0xC4, 0xD2, 0xA1, 0x48, 0x70,
+ 0xF7, 0x66, 0xE3, 0xBE, 0x15, 0xB5, 0xF5, 0x43,
+ 0x66, 0x12, 0x94, 0x56, 0x88, 0x31, 0xE6, 0xAC,
+ 0xC4, 0x54, 0x48, 0x9F, 0x51, 0x09, 0x3D, 0x95,
+ 0xA4, 0x83, 0x62, 0xD8, 0x47, 0x3D, 0xEB, 0xC4,
+ 0x5B, 0x6D, 0x38, 0x98, 0x93, 0x89, 0xF0, 0x1C,
+ 0x40, 0x00, 0x02, 0xE6, 0xCA, 0xDB, 0x95, 0xE6,
+ 0x8E, 0x44, 0xE0, 0x5F, 0xC9, 0x62, 0x55, 0x3F,
+ 0xC8, 0x48, 0x5D, 0x12, 0xE7, 0x01, 0x87, 0x5C,
+ 0x07, 0xF3, 0x0E, 0x0F, 0xD7, 0x89, 0x04, 0x3F,
+ 0x2A, 0x10, 0x70, 0xCC,
+
+ 0x3C, 0xB9, 0x3D, 0x28, 0x90, 0xEB, 0x21, 0x7D,
+ 0x9E, 0xCC, 0x4D, 0xA5, 0x84, 0xF6, 0x96, 0x93,
+ 0x5D, 0x12, 0x84, 0x9E, 0x71, 0x56, 0x5C, 0xD4,
+ 0x71, 0xB9, 0x9F, 0xDF, 0x2B, 0x51, 0x43, 0xC5,
+ 0x1E, 0x98, 0xBE, 0x8D, 0xB8, 0xFE, 0x3A, 0x9C,
+ 0x22, 0x25, 0xF2, 0x0F, 0x7F, 0x52, 0xB3, 0x9A,
+ 0xB6, 0xD8, 0x31, 0xE9, 0xC3, 0x9A, 0x86, 0x89,
+ 0xB6, 0x1B, 0x63, 0x3F, 0xC0, 0x37, 0x7D, 0xFF,
+ 0x80, 0xC3, 0x28, 0x0D, 0xF1, 0x09, 0xB1, 0xD1,
+ 0x38, 0xA8, 0x99, 0xD9, 0x81, 0x32, 0x62, 0x16,
+ 0xDE, 0x2D, 0x16, 0x07, 0x78, 0x5D, 0xCB, 0xB8,
+ 0x3E, 0xB8, 0x01, 0x5A, 0xB5, 0x21, 0x6E, 0xA1,
+ 0x7B, 0xD8, 0x64, 0x00, 0xFC, 0x6B, 0xDF, 0xA4,
+ 0x4D, 0x07, 0x81, 0xEE, 0x76, 0x69, 0x43, 0x9F,
+ 0x90, 0x09, 0x24, 0x26, 0x72, 0xC5, 0x2F, 0xF5,
+ 0x50, 0x31, 0xC9, 0xB9, 0x3B, 0xAE, 0xDE, 0x1F,
+ 0x6B, 0xCC, 0xFA, 0xC6, 0xCB, 0xBC, 0xEC, 0x75,
+ 0x91, 0x3A, 0x0C, 0x5D, 0x13, 0xB9, 0x3E, 0x16,
+ 0x3C, 0xE4, 0xAC, 0x56, 0x60, 0x0C, 0x92, 0x2D,
+ 0x05, 0xD6, 0x1A, 0x01, 0xC4, 0x94, 0xAD, 0x19,
+ 0xEE, 0x3C, 0x79, 0x5D, 0x5C, 0x49, 0x8A, 0x67,
+ 0xAF, 0x19, 0x1B, 0xBA, 0x2C, 0x30, 0xA2, 0x47,
+ 0xF2, 0x35, 0x00, 0x15, 0xF0, 0x7B, 0xC1, 0xA2,
+ 0xB3, 0x9C, 0x49, 0x83, 0x81, 0x26, 0x71, 0x7E,
+ 0xF0, 0x34, 0x01, 0x02, 0xC0, 0xDE, 0x44, 0xFA,
+ 0xFA, 0x5F, 0x84, 0xBA, 0x23, 0x16, 0x39, 0x29,
+ 0x77, 0xD7, 0x5D, 0x17, 0xBA, 0x9A, 0x39, 0x93,
+ 0xBE, 0xBB, 0x01, 0x67, 0xD6, 0x23, 0x2B, 0x7F,
+ 0x9E, 0x29, 0x61, 0xCC, 0x4D,
+
+ 0xCE, 0x24, 0x29, 0x8D, 0x54, 0x03, 0x84, 0x07,
+ 0xF8, 0x5A, 0x69, 0x9A, 0x3E, 0x01, 0xF5, 0x63,
+ 0xFC, 0x16, 0xB6, 0xF0, 0x20, 0x39, 0x81, 0x10,
+ 0xCD, 0x82, 0xD5, 0x5D, 0xAE, 0xED, 0xA6, 0x86,
+ 0xA5, 0xFF, 0xF8, 0x85, 0x6E, 0x0A, 0x36, 0x2F,
+ 0x6B, 0xF6, 0x62, 0xAB, 0x12, 0xE6, 0x41, 0x2B,
+ 0x3D, 0x4D, 0xDB, 0x80, 0x26, 0xC9, 0xAD, 0xE4,
+ 0x93, 0x05, 0x0C, 0x28, 0x23, 0xFF, 0x9B, 0xBF,
+ 0x85, 0x43, 0x82, 0xCD, 0x6E, 0x5F, 0xD4, 0x08,
+ 0x31, 0xFA, 0x52, 0x78, 0x99, 0x15, 0xD0, 0xD5,
+ 0xBD, 0x7C, 0xD4, 0x91, 0xCB, 0x0F, 0x53, 0xE7,
+ 0x5D, 0x53, 0xE8, 0xDA, 0xAB, 0x32, 0xDF, 0xD8,
+ 0xCF, 0xF5, 0x95, 0xF1, 0x41, 0xCF, 0x37, 0x2B,
+ 0xF0, 0x51, 0x93, 0x33, 0xAA, 0xFF, 0x36, 0x07,
+ 0x3C, 0xF9, 0x40, 0x18, 0x05, 0xA6, 0x1B, 0xEF,
+ 0x9E, 0x5E, 0x71, 0x77, 0x75, 0xD2, 0x23, 0xD6,
+ 0x0F, 0x5A, 0x84, 0x73, 0x6C, 0x23, 0x17, 0x18,
+ 0x78, 0x84, 0x41, 0xEC, 0x76, 0xD5, 0x66, 0xDE,
+ 0xF3, 0x22, 0x6E, 0x03, 0xD0, 0xF0, 0xFE, 0x67,
+ 0x8C, 0x4B, 0x4F, 0x43, 0xC8, 0x94, 0xBE, 0x8D,
+ 0x3C, 0x34, 0xA9, 0x1E, 0xC2, 0x27, 0x64, 0x90,
+ 0x13, 0x85, 0xA7, 0xC1, 0xC9, 0xF3, 0x6E, 0x50,
+ 0x0B, 0xD5, 0xD1, 0x38, 0xB0, 0x53, 0x0D, 0xDC,
+ 0x5A, 0xE8, 0x6B, 0x30, 0x91, 0xA2, 0x73, 0xDA,
+ 0x5C, 0xB3, 0x77, 0x36, 0xBC, 0xE1, 0xBF, 0xE0,
+ 0x85, 0x3B, 0xAC, 0x73, 0x13, 0xD1, 0x72, 0x0D,
+ 0x36, 0x47, 0xAE, 0x77, 0xA9, 0x91, 0x3B, 0x65,
+ 0x3F, 0x20, 0xED, 0x65, 0x02, 0x98, 0xAE, 0x1B,
+ 0x6B, 0x22, 0x17, 0x9F, 0x10, 0x64,
+
+ 0x43, 0xA6, 0xF3, 0x60, 0x88, 0x3A, 0x74, 0x66,
+ 0xA5, 0x48, 0xB2, 0x8F, 0x82, 0x94, 0xCC, 0xFD,
+ 0xCB, 0x15, 0x13, 0x60, 0x9B, 0xE4, 0x97, 0x96,
+ 0x2E, 0x36, 0xF9, 0xB3, 0x7B, 0xEC, 0xF1, 0xC3,
+ 0x54, 0xF0, 0xBB, 0xA0, 0xA8, 0x4A, 0x28, 0xB7,
+ 0x3A, 0x2E, 0xEC, 0x36, 0x5D, 0x0F, 0x26, 0xDE,
+ 0x3A, 0x24, 0x53, 0x13, 0x3F, 0xEA, 0x7C, 0x03,
+ 0xEB, 0x83, 0x53, 0x76, 0x8E, 0x83, 0xBC, 0x15,
+ 0x77, 0x04, 0xCC, 0xEF, 0x16, 0x7A, 0x40, 0xBA,
+ 0x14, 0xAB, 0x79, 0xB3, 0x2C, 0x18, 0xCE, 0xEC,
+ 0xC0, 0xF0, 0x66, 0x61, 0x99, 0xF7, 0x31, 0x3C,
+ 0x69, 0x66, 0xB5, 0xC0, 0xF4, 0x22, 0x4E, 0xCC,
+ 0x8A, 0xE9, 0xAC, 0x94, 0xC7, 0xC4, 0xC0, 0x88,
+ 0xCB, 0xF3, 0x4C, 0x49, 0xD1, 0x87, 0x55, 0xB8,
+ 0x15, 0x34, 0x47, 0x4B, 0xF0, 0x5B, 0xB3, 0xBB,
+ 0x77, 0x15, 0xED, 0x3F, 0xF8, 0x4F, 0xD3, 0x9D,
+ 0xFE, 0x8C, 0xD5, 0x4C, 0xE1, 0x2B, 0x74, 0x6F,
+ 0xA3, 0xBF, 0x03, 0x8A, 0xDF, 0xC2, 0xBF, 0xC5,
+ 0x27, 0x0F, 0xAF, 0x53, 0x42, 0x9A, 0x69, 0x39,
+ 0x33, 0xC7, 0x73, 0x67, 0x2E, 0xCE, 0x88, 0xD6,
+ 0xCF, 0xBB, 0x7C, 0xCB, 0x0D, 0x84, 0x0E, 0xB9,
+ 0x54, 0xFD, 0x51, 0x9F, 0xE3, 0x62, 0x87, 0xC7,
+ 0x5F, 0x08, 0xFE, 0x4C, 0x2E, 0xEA, 0x7F, 0xF2,
+ 0xC6, 0xB8, 0xEB, 0xDC, 0x35, 0x02, 0x1A, 0x6C,
+ 0xEB, 0xC0, 0x73, 0x82, 0x34, 0x52, 0xBE, 0x55,
+ 0x14, 0xB9, 0x36, 0x3D, 0xC8, 0x88, 0x03, 0x51,
+ 0x35, 0x7D, 0x89, 0x1B, 0x36, 0xA9, 0xD4, 0x03,
+ 0xA0, 0x86, 0x66, 0x90, 0x10, 0xC0, 0xBD, 0x39,
+ 0x5D, 0xB5, 0x4A, 0x67, 0x49, 0x2A, 0xBC,
+
+ 0x05, 0x95, 0xB2, 0x93, 0x14, 0x73, 0xB3, 0x70,
+ 0x89, 0xE4, 0xCC, 0x29, 0x8C, 0x60, 0x49, 0x46,
+ 0xBD, 0xC5, 0x33, 0x19, 0x32, 0xEE, 0xC7, 0xFA,
+ 0x6B, 0x93, 0x8B, 0x09, 0x75, 0x6D, 0xC6, 0x81,
+ 0xFA, 0xE9, 0xB1, 0x91, 0xBE, 0x74, 0xDF, 0x09,
+ 0xB6, 0xDB, 0x98, 0x67, 0x26, 0x7E, 0x8C, 0x0F,
+ 0x27, 0x5D, 0x38, 0x22, 0xCE, 0x70, 0x60, 0x7A,
+ 0xA1, 0xA5, 0x2F, 0xCC, 0x71, 0x18, 0x0C, 0x17,
+ 0x3D, 0x2A, 0xDD, 0xEC, 0xFA, 0xCB, 0x5B, 0x0E,
+ 0xD4, 0x4C, 0x3D, 0xED, 0x8A, 0xDE, 0xA5, 0x3D,
+ 0x1E, 0x35, 0xE4, 0xAB, 0xAF, 0x14, 0x5F, 0xF0,
+ 0x3F, 0xA0, 0x11, 0x5A, 0xC5, 0x64, 0x40, 0xEC,
+ 0x11, 0x90, 0x70, 0xDE, 0x01, 0x7F, 0xAD, 0xAE,
+ 0xE1, 0x30, 0x94, 0x6E, 0x1E, 0xE3, 0x22, 0xCD,
+ 0xC3, 0x91, 0x25, 0x77, 0x25, 0x9A, 0x62, 0xFA,
+ 0x43, 0xAC, 0x32, 0x8E, 0xE7, 0xB7, 0xF2, 0xD0,
+ 0x54, 0xD4, 0xC4, 0x6C, 0xB3, 0x88, 0xDD, 0xDA,
+ 0x82, 0xD6, 0xA4, 0x33, 0xC1, 0xAA, 0x42, 0xD1,
+ 0x26, 0x0C, 0xE7, 0xEC, 0x81, 0x87, 0x50, 0x56,
+ 0x00, 0xC0, 0xAC, 0xEE, 0x96, 0xBC, 0x67, 0xEB,
+ 0x03, 0x58, 0x38, 0x67, 0x71, 0x1B, 0xD8, 0x59,
+ 0xA2, 0xC5, 0x77, 0xA4, 0xD5, 0x39, 0x95, 0x13,
+ 0x60, 0x3C, 0x4F, 0x28, 0xD4, 0xB2, 0x9E, 0x15,
+ 0x3D, 0xB5, 0x24, 0x37, 0x32, 0xCC, 0x2C, 0x22,
+ 0xD3, 0x02, 0xAF, 0x60, 0x7F, 0x8E, 0x56, 0x59,
+ 0xC7, 0x52, 0x1A, 0xF7, 0x43, 0x70, 0x6E, 0xE6,
+ 0xFF, 0x2C, 0x94, 0x22, 0x85, 0x28, 0xEF, 0x24,
+ 0x83, 0x7F, 0x80, 0xAF, 0x4E, 0x7F, 0x37, 0x21,
+ 0x78, 0x9B, 0x31, 0x2E, 0x3A, 0xC0, 0xCE, 0x49,
+
+ 0x1C, 0x1A, 0x99, 0x58, 0xBA, 0x52, 0xC5, 0x41,
+ 0xFB, 0x0A, 0x17, 0xAF, 0x23, 0x3B, 0xBF, 0x3D,
+ 0x5B, 0x70, 0x45, 0xB9, 0xC2, 0xF4, 0xD5, 0xB2,
+ 0xF9, 0x5E, 0x82, 0xC0, 0x19, 0x99, 0x3F, 0xCB,
+ 0x22, 0xEC, 0x10, 0xF3, 0x26, 0xBA, 0xC7, 0xD4,
+ 0x9B, 0x2D, 0xFF, 0x3C, 0x39, 0xE4, 0xFB, 0x4D,
+ 0xC5, 0x5A, 0x01, 0x43, 0xBC, 0x83, 0x9F, 0x17,
+ 0x4E, 0xDC, 0xFE, 0x4B, 0x2E, 0x3C, 0x67, 0xA9,
+ 0x2A, 0xDB, 0xC4, 0x28, 0xB6, 0xD7, 0xB1, 0x24,
+ 0xDB, 0x10, 0xE6, 0x27, 0xF9, 0x29, 0xFC, 0x63,
+ 0x57, 0x72, 0xB6, 0xA0, 0x8C, 0x25, 0x7F, 0x67,
+ 0x94, 0x70, 0xBB, 0xBF, 0x2F, 0x60, 0xF4, 0xF3,
+ 0x98, 0x85, 0xBD, 0xE6, 0x50, 0xDC, 0xA6, 0x0E,
+ 0x96, 0xE7, 0x9F, 0x3C, 0x4F, 0xAE, 0xC7, 0x95,
+ 0xDB, 0x67, 0xEC, 0x20, 0x54, 0x2B, 0x34, 0xFA,
+ 0x04, 0x98, 0x77, 0xEE, 0xAD, 0xE4, 0x65, 0x94,
+ 0x94, 0xD6, 0x6D, 0xE0, 0x81, 0x15, 0x1F, 0x10,
+ 0x0F, 0x34, 0xEE, 0x64, 0x47, 0xD4, 0x15, 0x07,
+ 0xF4, 0x38, 0xC5, 0xEE, 0x06, 0x6F, 0x8A, 0xE6,
+ 0x7A, 0x18, 0x2E, 0x2E, 0xAB, 0xE7, 0xD9, 0x5C,
+ 0xD6, 0x58, 0xE4, 0x22, 0x21, 0xFB, 0xE0, 0x34,
+ 0x46, 0xE1, 0xBE, 0x89, 0x17, 0xC7, 0x8A, 0xD7,
+ 0x22, 0xE6, 0xE4, 0xDF, 0xA8, 0xCE, 0xFF, 0x2D,
+ 0xC4, 0x63, 0xF8, 0x83, 0x70, 0x3B, 0x4F, 0xB6,
+ 0x62, 0xA0, 0x50, 0x46, 0x30, 0xB1, 0x3E, 0xE8,
+ 0x2E, 0xBE, 0xFC, 0xAA, 0x5C, 0xF5, 0x68, 0xB3,
+ 0x47, 0xBF, 0x65, 0x3E, 0x64, 0x72, 0x6F, 0x90,
+ 0x89, 0x88, 0x2F, 0x82, 0x35, 0xE9, 0xF6, 0xD1,
+ 0xFA, 0xEE, 0x25, 0xDC, 0xA0, 0x04, 0xD7, 0x0B,
+ 0x1E,
+
+ 0xED, 0x32, 0x54, 0xE8, 0x2D, 0x03, 0x35, 0xD5,
+ 0x55, 0x62, 0x1F, 0xD2, 0x2A, 0xE5, 0x69, 0x47,
+ 0xD6, 0xD8, 0x92, 0xBC, 0x3D, 0xF1, 0xAB, 0x57,
+ 0xFE, 0x03, 0x12, 0xCE, 0xAD, 0xF8, 0x1D, 0x37,
+ 0xB2, 0x40, 0x72, 0xD0, 0xC8, 0x38, 0xE2, 0xD1,
+ 0xA4, 0x0F, 0xA0, 0x7F, 0x19, 0x72, 0xAF, 0x84,
+ 0x53, 0x8B, 0x71, 0x66, 0xBF, 0x56, 0x19, 0x3A,
+ 0xEA, 0x27, 0xFD, 0xF5, 0xB6, 0x43, 0xD4, 0xB8,
+ 0x8B, 0x27, 0xE8, 0x82, 0x0B, 0x24, 0x3C, 0xD7,
+ 0xFF, 0x31, 0xF3, 0x6D, 0x15, 0x5D, 0xBD, 0x1D,
+ 0x93, 0x0F, 0x98, 0x4E, 0x16, 0x00, 0x94, 0xEE,
+ 0xE6, 0x27, 0xBA, 0x19, 0xC2, 0xCE, 0x73, 0x63,
+ 0x0C, 0x71, 0xEC, 0x27, 0x70, 0x69, 0x2E, 0x96,
+ 0xA3, 0x20, 0x98, 0xCF, 0x2B, 0xDF, 0x50, 0x07,
+ 0xC8, 0x10, 0xCD, 0xA0, 0x6B, 0x9E, 0xBF, 0xEC,
+ 0xD3, 0x6E, 0x94, 0x70, 0x6B, 0x3F, 0xE1, 0x73,
+ 0x10, 0xDB, 0x9E, 0x98, 0x5B, 0x5B, 0x97, 0xB9,
+ 0x07, 0xF4, 0xD6, 0x55, 0xEC, 0x52, 0x86, 0x0E,
+ 0x14, 0xD5, 0xF9, 0x5F, 0xA9, 0xFB, 0xE1, 0x96,
+ 0x6E, 0xB1, 0xA8, 0xB0, 0xD3, 0xB1, 0x44, 0x08,
+ 0xF8, 0xBC, 0x97, 0xC8, 0xF7, 0xE8, 0xD5, 0xC9,
+ 0xD7, 0x9F, 0x2C, 0xCA, 0xC6, 0x35, 0x26, 0x4F,
+ 0x2F, 0x83, 0xC0, 0x88, 0x91, 0x8D, 0x9A, 0xD7,
+ 0xFC, 0x8A, 0x2A, 0x9C, 0x06, 0x8C, 0xFA, 0xC3,
+ 0xF3, 0xD0, 0x0A, 0x21, 0xE3, 0x4E, 0xDF, 0x6A,
+ 0xB4, 0x00, 0x9F, 0xF4, 0xB6, 0x6E, 0x41, 0xF2,
+ 0x1A, 0x5E, 0xC8, 0x8B, 0x36, 0xC2, 0x81, 0xDA,
+ 0x0C, 0x74, 0x20, 0xC5, 0x41, 0x60, 0xD1, 0x2A,
+ 0xEB, 0xAA, 0x51, 0xCB, 0x38, 0x10, 0x94, 0x8B,
+ 0xA2, 0x89,
+
+ 0x90, 0xBB, 0xE5, 0x2E, 0xDE, 0xBA, 0xB1, 0x0F,
+ 0x5C, 0xB8, 0x39, 0x67, 0xF9, 0x10, 0x1A, 0x72,
+ 0x33, 0xA4, 0x9B, 0x47, 0x5C, 0xC3, 0x97, 0x66,
+ 0xA9, 0x31, 0xC6, 0xD6, 0xD1, 0x64, 0x51, 0x19,
+ 0x3A, 0xAC, 0xBF, 0x99, 0x1B, 0x1C, 0xEC, 0x32,
+ 0x4F, 0x69, 0xC7, 0x6D, 0xBD, 0x4A, 0xEE, 0x29,
+ 0x75, 0x66, 0x42, 0xF7, 0x40, 0x58, 0xE5, 0x05,
+ 0x84, 0x18, 0x8A, 0x82, 0xE8, 0x8E, 0x13, 0x19,
+ 0x89, 0x6F, 0xC1, 0xDD, 0x43, 0x0C, 0xC5, 0x63,
+ 0xE2, 0xC4, 0xCC, 0x33, 0x61, 0xF4, 0xE6, 0x6B,
+ 0x9B, 0x39, 0x5E, 0xA1, 0x8E, 0x80, 0x8C, 0x13,
+ 0x1B, 0xE5, 0xD4, 0x4D, 0x7A, 0xDD, 0xF4, 0x52,
+ 0x51, 0x0C, 0x0B, 0x1F, 0x23, 0x52, 0xC8, 0x52,
+ 0xF8, 0xD4, 0x88, 0x3E, 0xAE, 0xB8, 0x98, 0xF8,
+ 0x76, 0xB3, 0xAD, 0x6B, 0x20, 0xD4, 0x83, 0x87,
+ 0x68, 0x45, 0x5C, 0xA8, 0xB3, 0xA0, 0xA4, 0xB9,
+ 0xE7, 0x16, 0x06, 0x48, 0xEF, 0x45, 0x33, 0x29,
+ 0xAB, 0x75, 0xE6, 0x9D, 0x83, 0x74, 0xF9, 0xF7,
+ 0x22, 0xA0, 0xC5, 0xFF, 0x9E, 0x35, 0x6A, 0x46,
+ 0x7B, 0x80, 0x21, 0xE7, 0x47, 0xD8, 0x4C, 0x37,
+ 0xB1, 0x96, 0x05, 0xBD, 0xE2, 0x1B, 0xDF, 0xE9,
+ 0x34, 0x4B, 0xBF, 0x03, 0x72, 0xB8, 0x47, 0x6E,
+ 0xE4, 0xB8, 0xDB, 0x63, 0xD6, 0xC2, 0x62, 0x8E,
+ 0xA8, 0x28, 0x1F, 0xC3, 0x1C, 0x35, 0x1F, 0x2C,
+ 0xCD, 0x24, 0xAF, 0x6A, 0x38, 0x1D, 0xA1, 0xC8,
+ 0x07, 0xA7, 0xB7, 0x04, 0x5A, 0xC6, 0x08, 0x4E,
+ 0x29, 0xBB, 0xA2, 0x19, 0xFE, 0x54, 0x2F, 0xD8,
+ 0xF3, 0xB3, 0x3E, 0x60, 0xFF, 0x27, 0xB1, 0x88,
+ 0x2F, 0x2C, 0xB7, 0x66, 0x09, 0x97, 0xE5, 0x09,
+ 0x77, 0x5F, 0x53,
+
+ 0xD3, 0xA5, 0x23, 0x44, 0x45, 0xCA, 0x7B, 0xF1,
+ 0x84, 0xF2, 0x59, 0x2F, 0x75, 0xC6, 0xC3, 0x49,
+ 0xEC, 0x4C, 0xA2, 0x4A, 0xF9, 0xD1, 0xBB, 0x1D,
+ 0xBB, 0x30, 0x2E, 0x18, 0xDD, 0xFF, 0xC8, 0x77,
+ 0x2D, 0x8F, 0x09, 0x6F, 0x65, 0x5A, 0x64, 0x6B,
+ 0xEB, 0x8A, 0xDF, 0xA2, 0x50, 0xBA, 0x5A, 0x54,
+ 0x79, 0xE5, 0x14, 0x69, 0x42, 0x34, 0xE8, 0xA0,
+ 0x62, 0xA5, 0x3A, 0x7A, 0x49, 0xB1, 0x8B, 0xA3,
+ 0xD8, 0x73, 0x57, 0x70, 0xE3, 0x93, 0x04, 0xE4,
+ 0x59, 0x86, 0x8A, 0x7B, 0xBE, 0x65, 0x48, 0x16,
+ 0xB5, 0xE6, 0xAF, 0xC3, 0xBD, 0xFF, 0x3C, 0xDF,
+ 0xF6, 0xCB, 0x60, 0xE4, 0xBA, 0x77, 0xF4, 0x4B,
+ 0x95, 0x79, 0xCE, 0xD6, 0x36, 0xBD, 0xBF, 0x36,
+ 0x42, 0x53, 0x15, 0xA3, 0x77, 0xB3, 0x9F, 0x68,
+ 0x98, 0x6E, 0xB5, 0x01, 0x16, 0xA2, 0x26, 0x79,
+ 0xB0, 0x1A, 0x65, 0x45, 0x30, 0xBB, 0x00, 0x4F,
+ 0xE4, 0x7A, 0xD0, 0x31, 0xE5, 0x77, 0xD4, 0xC6,
+ 0x6A, 0x72, 0xC5, 0xF2, 0xC1, 0xFC, 0x60, 0x74,
+ 0x99, 0xD5, 0x25, 0xF2, 0x7B, 0x6D, 0xFE, 0x32,
+ 0x1C, 0x90, 0xD0, 0xF9, 0xF0, 0xAE, 0x93, 0x20,
+ 0xB4, 0xA0, 0xF7, 0xA5, 0x75, 0xE4, 0x83, 0x94,
+ 0x80, 0x8C, 0x1E, 0x18, 0xD7, 0x1C, 0xA4, 0x5F,
+ 0x0A, 0x08, 0xD2, 0xB1, 0x27, 0xC4, 0x0D, 0xA4,
+ 0xBE, 0xE0, 0x36, 0x69, 0x19, 0x14, 0x9A, 0x58,
+ 0x9C, 0xD5, 0x36, 0xE5, 0x46, 0xE1, 0x94, 0x66,
+ 0xC3, 0x77, 0x78, 0x52, 0xF9, 0x2B, 0xDA, 0x95,
+ 0xDC, 0xED, 0x6A, 0x6E, 0x58, 0xE9, 0x16, 0x34,
+ 0x2A, 0x6B, 0xD5, 0x4E, 0xF2, 0x7E, 0xB8, 0x96,
+ 0xEB, 0x9B, 0x4D, 0xD3, 0xFD, 0xB4, 0x33, 0x0D,
+ 0x13, 0x26, 0x42, 0x3E,
+
+ 0xF6, 0x0F, 0x59, 0xEC, 0xB0, 0xE1, 0x3D, 0x20,
+ 0xB8, 0xD7, 0x3D, 0xF9, 0x59, 0xCF, 0xEF, 0xA9,
+ 0xD7, 0xB2, 0x47, 0xBC, 0x87, 0x54, 0xD3, 0x7E,
+ 0xF9, 0x2C, 0xDF, 0xB6, 0x0F, 0x86, 0x13, 0x02,
+ 0x1C, 0xFA, 0xC0, 0x26, 0xDB, 0x49, 0x3B, 0x36,
+ 0x60, 0xA2, 0x64, 0xD8, 0x91, 0xB1, 0x7C, 0x35,
+ 0xEA, 0x2F, 0x5E, 0xF6, 0x99, 0xE2, 0x0B, 0x74,
+ 0x1F, 0x76, 0xF6, 0x8F, 0x7E, 0x58, 0x63, 0x3E,
+ 0xB6, 0xA2, 0xF3, 0x0A, 0xD4, 0xA5, 0x19, 0xB7,
+ 0x45, 0x08, 0xDB, 0x52, 0x17, 0x1D, 0xB1, 0x00,
+ 0x23, 0x0B, 0xD4, 0xC0, 0x86, 0x52, 0x49, 0xA8,
+ 0x33, 0xAB, 0x0A, 0xD1, 0x51, 0x9C, 0x5D, 0x4B,
+ 0x23, 0xF1, 0x93, 0x17, 0x6A, 0x48, 0xA6, 0x2F,
+ 0x9D, 0x0D, 0x9A, 0x09, 0xBD, 0x19, 0xA0, 0x39,
+ 0x60, 0xDE, 0xD1, 0xE4, 0x42, 0xD8, 0x34, 0xC0,
+ 0x1D, 0xD3, 0x88, 0x29, 0xA8, 0x48, 0x75, 0x5C,
+ 0xDF, 0x1D, 0xD4, 0x09, 0x53, 0x5E, 0x5D, 0x0A,
+ 0x9A, 0x2D, 0x95, 0x83, 0xF6, 0x85, 0x2F, 0xAD,
+ 0x8C, 0xFF, 0x55, 0xD8, 0x19, 0x56, 0xEE, 0x38,
+ 0xD2, 0x25, 0x30, 0x27, 0x21, 0xB5, 0x10, 0xED,
+ 0x24, 0xFB, 0x0E, 0x22, 0x55, 0xA2, 0xC3, 0x31,
+ 0xDC, 0x1E, 0xA0, 0xC7, 0x4B, 0x1B, 0xC0, 0x14,
+ 0x95, 0x25, 0x8F, 0x37, 0x3C, 0x75, 0x61, 0x44,
+ 0x0B, 0x09, 0x81, 0x8C, 0x32, 0xE5, 0x59, 0x3D,
+ 0xE3, 0xD5, 0x45, 0xDF, 0x11, 0xFF, 0x61, 0x9E,
+ 0x01, 0x10, 0x5E, 0x91, 0x70, 0x18, 0x1D, 0x76,
+ 0xC9, 0x74, 0x3C, 0xDD, 0x30, 0xB2, 0x01, 0xF5,
+ 0xCD, 0xCD, 0x9F, 0xFC, 0xE3, 0x7A, 0xB9, 0xD1,
+ 0x7F, 0xA4, 0x3C, 0x2E, 0x2C, 0x28, 0x25, 0xCC,
+ 0x6C, 0x56, 0x3A, 0x80, 0xF9,
+
+ 0x7E, 0x13, 0xEF, 0xE6, 0x6B, 0x69, 0x25, 0xE0,
+ 0x81, 0xE9, 0x64, 0x4E, 0xE9, 0xFC, 0x00, 0x0C,
+ 0xDD, 0x81, 0x66, 0xB1, 0xC9, 0x12, 0xC4, 0x98,
+ 0x5F, 0x71, 0x2F, 0xFC, 0xFB, 0x24, 0x9E, 0x49,
+ 0x5E, 0xFB, 0x20, 0xB9, 0x56, 0x06, 0x23, 0xD3,
+ 0xD5, 0x80, 0x51, 0x25, 0xE6, 0x33, 0x55, 0xC0,
+ 0x48, 0x28, 0x32, 0xDB, 0xBB, 0x48, 0x6D, 0xF6,
+ 0x30, 0xA7, 0x4D, 0xC6, 0x54, 0x7A, 0x63, 0x5E,
+ 0x54, 0x7A, 0xE4, 0xEB, 0x71, 0x03, 0xA7, 0x65,
+ 0x1F, 0x36, 0x25, 0x32, 0xD0, 0x3F, 0xA1, 0x07,
+ 0xAB, 0xE0, 0x17, 0x57, 0x18, 0x06, 0xCB, 0x2B,
+ 0x78, 0x9F, 0xC3, 0xBD, 0x57, 0x13, 0x4B, 0x0A,
+ 0x52, 0xFC, 0x87, 0x39, 0xFF, 0xE6, 0xE8, 0x89,
+ 0x1D, 0x65, 0x61, 0x36, 0x6B, 0x93, 0xB8, 0xA9,
+ 0x71, 0x4B, 0xB3, 0xD4, 0x87, 0xBF, 0xAF, 0x89,
+ 0xB7, 0x57, 0x8F, 0x11, 0x3D, 0x36, 0xF2, 0x13,
+ 0x89, 0x92, 0x7C, 0xD6, 0xFE, 0x18, 0x9F, 0x4A,
+ 0x7F, 0xBE, 0x34, 0x1F, 0xAF, 0xCB, 0xFB, 0xCA,
+ 0x74, 0x7B, 0x4D, 0x93, 0x71, 0x45, 0xE4, 0xA0,
+ 0x4E, 0xE7, 0x4B, 0x9E, 0xFE, 0x45, 0x13, 0xDB,
+ 0xE9, 0x26, 0xD8, 0x75, 0xA5, 0xB6, 0x8A, 0x5E,
+ 0xF7, 0x7A, 0xE1, 0xA6, 0x78, 0xEB, 0xBA, 0xBA,
+ 0xC6, 0xB2, 0xC2, 0xCF, 0x04, 0x8A, 0x72, 0x6C,
+ 0xA2, 0x53, 0xDE, 0xC8, 0x91, 0xDB, 0x05, 0x46,
+ 0xA4, 0x86, 0x0C, 0xB8, 0xD0, 0x0F, 0x15, 0x10,
+ 0xD4, 0xC3, 0xA1, 0x53, 0xEA, 0x9F, 0x9A, 0x20,
+ 0x5A, 0xB3, 0xE8, 0x7A, 0x47, 0xC8, 0xCF, 0x87,
+ 0xA3, 0x7D, 0x54, 0x5C, 0xF1, 0x84, 0xE2, 0x5E,
+ 0x8A, 0x98, 0x8E, 0x7F, 0xAE, 0x18, 0x2F, 0x97,
+ 0xB3, 0x5D, 0x84, 0xFF, 0xEC, 0xAB,
+
+ 0x81, 0x65, 0x82, 0x11, 0xCB, 0x36, 0xCA, 0xE9,
+ 0x04, 0x0E, 0x35, 0x85, 0xBE, 0xB3, 0x99, 0xDF,
+ 0xCF, 0xD5, 0x77, 0x38, 0xD4, 0xDC, 0xFE, 0x0D,
+ 0x01, 0xD3, 0x06, 0x2E, 0x83, 0x2E, 0x3A, 0x8C,
+ 0x90, 0x84, 0x17, 0x74, 0x28, 0x79, 0xFB, 0x3C,
+ 0x4B, 0x6D, 0x22, 0x43, 0xD6, 0x54, 0x6C, 0x6D,
+ 0x04, 0x36, 0xD7, 0x75, 0x95, 0xA0, 0xA8, 0xD1,
+ 0x42, 0xAC, 0x4B, 0x97, 0xAD, 0x69, 0x3F, 0xBA,
+ 0x2C, 0x0B, 0xC2, 0xCD, 0x3D, 0x70, 0x31, 0xEE,
+ 0xE6, 0x9E, 0x81, 0x28, 0x42, 0xAF, 0x67, 0x5D,
+ 0x3C, 0xFE, 0xDA, 0xF8, 0x89, 0x2F, 0xF8, 0xA0,
+ 0x19, 0x4E, 0x77, 0x87, 0x45, 0xBC, 0x0D, 0xB6,
+ 0xC0, 0x16, 0xE3, 0x4D, 0x46, 0x03, 0x89, 0x70,
+ 0xB0, 0xF3, 0xD3, 0x6F, 0x9A, 0x30, 0xD7, 0x51,
+ 0x05, 0xAE, 0xCC, 0x3A, 0xC5, 0x68, 0x56, 0x93,
+ 0x7B, 0x0F, 0x37, 0x96, 0x0E, 0x91, 0xD5, 0x7D,
+ 0xF9, 0xA6, 0xEB, 0x2C, 0x4E, 0xF6, 0x19, 0x0A,
+ 0xBA, 0x0F, 0x84, 0xA9, 0xD1, 0xFC, 0xD4, 0x72,
+ 0x0B, 0xCD, 0x79, 0xDE, 0x05, 0x49, 0x62, 0x4A,
+ 0x89, 0xEE, 0xB5, 0x6D, 0x5C, 0x28, 0xA7, 0xC7,
+ 0x96, 0x99, 0xF1, 0x0D, 0x35, 0xE2, 0xB3, 0x0E,
+ 0x20, 0xDB, 0x0A, 0xAD, 0x32, 0x72, 0x42, 0x40,
+ 0x60, 0x68, 0x39, 0xE1, 0xD9, 0x2E, 0x74, 0x90,
+ 0x59, 0xC7, 0xF1, 0xAE, 0x35, 0xC4, 0x0D, 0x8B,
+ 0xCE, 0xB1, 0xDC, 0x60, 0xD7, 0x03, 0x5A, 0x03,
+ 0xCD, 0x6F, 0xED, 0xC8, 0x8A, 0xF2, 0x5A, 0xE5,
+ 0x88, 0xBB, 0x24, 0xA5, 0x6C, 0x8E, 0x95, 0x84,
+ 0xF3, 0x02, 0x78, 0x5E, 0x7C, 0x8E, 0xDF, 0xCF,
+ 0xB1, 0x48, 0x5F, 0x16, 0x73, 0x38, 0x46, 0x69,
+ 0x3E, 0x41, 0x82, 0xBE, 0x29, 0xEC, 0xAF,
+
+ 0x35, 0x6C, 0x92, 0x8B, 0x5B, 0xA9, 0xD1, 0x04,
+ 0x67, 0x82, 0x3C, 0x7E, 0x26, 0xA3, 0x0B, 0x58,
+ 0xD2, 0xC7, 0xC2, 0x3E, 0xC3, 0xDF, 0x79, 0x69,
+ 0xA6, 0x73, 0x38, 0xDC, 0x01, 0x60, 0x17, 0x37,
+ 0xD7, 0x46, 0xF4, 0xE6, 0x62, 0x72, 0xC7, 0x09,
+ 0xDB, 0x6F, 0x45, 0xDE, 0x59, 0x85, 0x48, 0xA1,
+ 0xA4, 0xF7, 0x6D, 0x83, 0x52, 0xC0, 0x64, 0xE3,
+ 0x4B, 0xFB, 0xCD, 0xAB, 0x62, 0x10, 0xF7, 0x40,
+ 0x07, 0xAA, 0x51, 0x83, 0xCF, 0xD8, 0xFD, 0xC1,
+ 0x35, 0x27, 0x0A, 0xCE, 0x21, 0x5E, 0x85, 0xF8,
+ 0x10, 0x0C, 0xAD, 0xCE, 0xD3, 0xB2, 0xF0, 0xCB,
+ 0x03, 0x4A, 0xE1, 0x8E, 0x8E, 0xF1, 0x05, 0xE3,
+ 0x1E, 0xBD, 0x35, 0xB3, 0x41, 0xEA, 0x39, 0x93,
+ 0xAD, 0xE2, 0xBC, 0xFD, 0x68, 0xCF, 0xAF, 0xDE,
+ 0x3F, 0xB3, 0xDD, 0xB3, 0x1A, 0x4C, 0x81, 0x6D,
+ 0x3E, 0x7E, 0x76, 0xA3, 0xB8, 0x26, 0x9D, 0xA4,
+ 0xD9, 0xAC, 0x88, 0x71, 0xEC, 0xE9, 0x4F, 0xA5,
+ 0xBF, 0x53, 0xB6, 0xFF, 0x52, 0xDA, 0xCB, 0x9B,
+ 0x2B, 0x67, 0xAF, 0x50, 0xEE, 0xCF, 0xA5, 0xD0,
+ 0x35, 0xAA, 0xB5, 0xE9, 0x34, 0x8E, 0x62, 0xD6,
+ 0x11, 0x94, 0xD0, 0xA7, 0xEF, 0xB9, 0xA2, 0x19,
+ 0x22, 0x17, 0xE4, 0x20, 0x35, 0xB6, 0x60, 0x8F,
+ 0x26, 0xAA, 0x3C, 0x41, 0xC8, 0xFC, 0xBC, 0xEE,
+ 0x5E, 0x42, 0xF6, 0x9B, 0x79, 0xBA, 0xAA, 0x4D,
+ 0x59, 0x18, 0xC9, 0x00, 0x9F, 0x28, 0x17, 0x3A,
+ 0x1F, 0xFC, 0x3B, 0x4C, 0xD5, 0xBF, 0x1B, 0x72,
+ 0x88, 0x5D, 0x22, 0x57, 0x7A, 0x47, 0x8A, 0x2C,
+ 0x19, 0x97, 0x80, 0x9A, 0x1C, 0x8A, 0x70, 0xA7,
+ 0xDA, 0xEB, 0xAE, 0x21, 0x81, 0x93, 0x63, 0xE9,
+ 0xDE, 0x12, 0xB2, 0xA6, 0xC3, 0x57, 0xD0, 0xD7,
+
+ 0x04, 0xCD, 0xA5, 0x8D, 0x82, 0x25, 0xCC, 0xAE,
+ 0xDB, 0x8A, 0xBB, 0xCE, 0x96, 0x7D, 0x69, 0x62,
+ 0x5F, 0x34, 0x39, 0x4C, 0x82, 0xD3, 0xC6, 0x1E,
+ 0x27, 0x44, 0xDF, 0x66, 0xF0, 0x66, 0xF1, 0xA4,
+ 0x3E, 0xC8, 0x72, 0x58, 0x7C, 0x78, 0x50, 0x1B,
+ 0xAE, 0x6D, 0x22, 0x40, 0x27, 0x70, 0x6C, 0x12,
+ 0x1D, 0x44, 0x70, 0x1B, 0xC6, 0xD5, 0x76, 0x76,
+ 0xDD, 0xC4, 0x63, 0xE9, 0x17, 0xFF, 0xE4, 0x93,
+ 0x67, 0x24, 0xE0, 0x2C, 0x51, 0x3E, 0xCA, 0x62,
+ 0xC7, 0x0B, 0x47, 0x84, 0xDF, 0x98, 0x94, 0x85,
+ 0x40, 0xF0, 0xAA, 0xFC, 0x74, 0xCC, 0x15, 0x7E,
+ 0x9B, 0x14, 0x2D, 0x78, 0x38, 0x88, 0x12, 0x4D,
+ 0xB3, 0xE4, 0x64, 0xEB, 0x38, 0x3C, 0x0F, 0xC7,
+ 0x08, 0x26, 0x06, 0x9D, 0xD4, 0xCD, 0xCD, 0xCA,
+ 0x10, 0xA1, 0x9B, 0xCD, 0x03, 0x92, 0x75, 0x32,
+ 0xA5, 0x0F, 0xAA, 0xA4, 0xB0, 0xFE, 0x6B, 0xB3,
+ 0x47, 0xFD, 0x58, 0x9F, 0x69, 0x6D, 0xD5, 0x93,
+ 0xE7, 0x46, 0x92, 0xF5, 0x6B, 0xA7, 0x07, 0xBC,
+ 0x5E, 0xE1, 0x9D, 0x7D, 0xF6, 0xB5, 0x01, 0x64,
+ 0x6D, 0xDE, 0x24, 0x8F, 0xEF, 0x17, 0x4F, 0x74,
+ 0x3A, 0x13, 0x2B, 0x67, 0x05, 0x3C, 0x3B, 0xE2,
+ 0x17, 0x01, 0xD7, 0xAC, 0x2C, 0xD2, 0xEE, 0x89,
+ 0xE7, 0x50, 0xAB, 0x0B, 0x3A, 0x03, 0x6A, 0x05,
+ 0x2B, 0xAF, 0x7A, 0x71, 0x6D, 0x59, 0x13, 0x22,
+ 0xD4, 0x7F, 0xE0, 0xD4, 0xD5, 0xE6, 0x37, 0x4E,
+ 0x81, 0x04, 0xB1, 0x5C, 0xE4, 0x81, 0xE4, 0xE0,
+ 0x1D, 0x11, 0xF6, 0x3E, 0xE7, 0xB8, 0x7E, 0xDB,
+ 0xB3, 0x72, 0xE9, 0x63, 0x6B, 0xB7, 0xAA, 0x20,
+ 0x94, 0x14, 0x8E, 0x1C, 0x6D, 0xD3, 0xF4, 0xE6,
+ 0x3F, 0x14, 0xDD, 0x3F, 0xA3, 0x8A, 0x5B, 0xC3,
+ 0x0A,
+
+ 0x10, 0x5A, 0xA3, 0x65, 0x9B, 0x9C, 0x5D, 0xBD,
+ 0x92, 0x5A, 0x84, 0x1B, 0x18, 0xA6, 0x4A, 0x43,
+ 0x69, 0xA2, 0xD2, 0x67, 0x8C, 0xC5, 0x90, 0xD6,
+ 0x33, 0xD7, 0xE5, 0x12, 0xEF, 0xCB, 0x68, 0x24,
+ 0xB9, 0x66, 0xF6, 0x69, 0xA5, 0x2D, 0x43, 0xDD,
+ 0xFC, 0x2C, 0x08, 0x3E, 0x71, 0xF3, 0x33, 0xF1,
+ 0xED, 0xBA, 0x0E, 0x8B, 0xE6, 0xF3, 0xA7, 0x90,
+ 0x61, 0xD9, 0x3B, 0xC6, 0xB6, 0x89, 0xEF, 0xE3,
+ 0x9C, 0x55, 0xCC, 0x92, 0xE0, 0xB7, 0xA8, 0xA2,
+ 0xBE, 0x6E, 0x3B, 0xF4, 0xC2, 0x47, 0x21, 0x0E,
+ 0x1B, 0xD8, 0x76, 0x19, 0x99, 0xCE, 0x97, 0x02,
+ 0x25, 0x37, 0x28, 0xC0, 0x8E, 0x13, 0x6E, 0xB7,
+ 0x1B, 0x6B, 0x7C, 0x40, 0x3E, 0x78, 0xD1, 0xD1,
+ 0x55, 0x84, 0xA7, 0x1E, 0x82, 0x5C, 0x5D, 0x8E,
+ 0x14, 0x2E, 0xF4, 0x5B, 0x76, 0xC7, 0xCB, 0x82,
+ 0x74, 0xB3, 0x6F, 0xF5, 0xFD, 0xDE, 0x74, 0xD5,
+ 0xBD, 0xFB, 0x37, 0xA9, 0x54, 0x90, 0x97, 0x08,
+ 0x5C, 0xA7, 0x13, 0x07, 0xC4, 0x8C, 0x0C, 0x51,
+ 0x5D, 0x22, 0x71, 0xFE, 0x25, 0x77, 0x13, 0x23,
+ 0x3C, 0x57, 0x04, 0xEC, 0xE5, 0xD4, 0x41, 0x4E,
+ 0xE7, 0xFA, 0x1B, 0x4A, 0x31, 0xE1, 0xC6, 0x35,
+ 0x99, 0x0D, 0x8B, 0xAC, 0x37, 0xAB, 0x38, 0x8C,
+ 0xEC, 0x59, 0x44, 0x8A, 0x5A, 0xD9, 0x7A, 0x99,
+ 0x95, 0x33, 0x7E, 0x65, 0xEF, 0x78, 0x63, 0xE2,
+ 0x6D, 0xFE, 0x7D, 0xAC, 0xA5, 0x05, 0x13, 0xB7,
+ 0x8E, 0xF2, 0x9B, 0x76, 0x7E, 0x6C, 0x54, 0x86,
+ 0xA2, 0xAA, 0x2F, 0x3B, 0x38, 0x46, 0x1D, 0x4E,
+ 0xDB, 0x36, 0x42, 0x88, 0x0D, 0x0C, 0x7B, 0xAF,
+ 0xAC, 0x58, 0x0B, 0x24, 0x99, 0xCB, 0x5E, 0x9D,
+ 0x6D, 0xDC, 0xE8, 0xE1, 0xDC, 0xD5, 0xC3, 0x31,
+ 0xBE, 0xD5,
+
+ 0xB0, 0xD1, 0xFC, 0x60, 0x3A, 0x61, 0x99, 0x7C,
+ 0xDD, 0x25, 0x09, 0x27, 0x2F, 0x4F, 0xEA, 0x8D,
+ 0x71, 0x0C, 0xE3, 0x47, 0x8A, 0xBC, 0xB6, 0xBD,
+ 0x8B, 0x6E, 0xFC, 0x63, 0x4A, 0x49, 0x59, 0xA4,
+ 0x4D, 0x2C, 0x8B, 0xDB, 0x9C, 0xFA, 0x23, 0xAE,
+ 0xDF, 0xBA, 0x3A, 0x1A, 0x21, 0xED, 0x74, 0x3F,
+ 0x20, 0xC1, 0x66, 0xCF, 0xBB, 0x21, 0x96, 0x57,
+ 0xD4, 0x9A, 0xFF, 0xCD, 0xB6, 0x21, 0xE4, 0xA6,
+ 0xC1, 0x38, 0xDA, 0x54, 0x20, 0x9B, 0x21, 0xC9,
+ 0x22, 0x5D, 0x1E, 0xCD, 0x48, 0x8C, 0x85, 0xE2,
+ 0xCA, 0x4D, 0xE3, 0xE3, 0x82, 0x9F, 0x3A, 0xB9,
+ 0xC1, 0xB9, 0x01, 0x50, 0x1F, 0x13, 0xB0, 0xDF,
+ 0x12, 0x2D, 0x09, 0x85, 0xA2, 0xD7, 0x0D, 0x9D,
+ 0x01, 0x92, 0xC9, 0xEC, 0xE5, 0x50, 0x58, 0xF0,
+ 0xF8, 0x58, 0x7F, 0xD1, 0xCF, 0xFD, 0x77, 0xBD,
+ 0x73, 0x6B, 0x9B, 0x9D, 0x35, 0x25, 0x1D, 0x52,
+ 0x6B, 0xF0, 0x8E, 0x78, 0xF2, 0xCF, 0x52, 0x11,
+ 0x17, 0xF3, 0xB2, 0x20, 0x80, 0x22, 0x90, 0x7B,
+ 0xBD, 0x1B, 0x32, 0x1D, 0x17, 0xF8, 0xB0, 0xB0,
+ 0xBC, 0x82, 0xC1, 0x20, 0x8E, 0x79, 0x17, 0x18,
+ 0x6B, 0x8D, 0xD3, 0x57, 0xBE, 0xB6, 0xB0, 0x48,
+ 0x23, 0x5D, 0x70, 0x50, 0xA7, 0x2C, 0x55, 0xC4,
+ 0x39, 0x88, 0x5C, 0x7C, 0xA5, 0x74, 0x43, 0xA4,
+ 0x8E, 0x02, 0x4C, 0x8E, 0x7E, 0x05, 0x73, 0x6B,
+ 0x89, 0x44, 0xAA, 0x84, 0xF4, 0xD4, 0x0F, 0xB9,
+ 0xB1, 0x8B, 0x0D, 0xD5, 0x38, 0x32, 0xBD, 0x84,
+ 0x49, 0xB6, 0x3E, 0xD9, 0x65, 0xAB, 0x96, 0x2A,
+ 0x6A, 0x47, 0xD5, 0x0E, 0x21, 0x4F, 0xF7, 0xF9,
+ 0xE4, 0xE9, 0x46, 0xA1, 0x09, 0x7A, 0x7B, 0x0E,
+ 0x10, 0x3D, 0x3D, 0xE8, 0xB1, 0xBB, 0x07, 0x1A,
+ 0x54, 0xBA, 0xC2,
+
+ 0x3C, 0xDD, 0x72, 0x30, 0xB1, 0xD2, 0x79, 0x40,
+ 0x8E, 0x03, 0x65, 0x7D, 0x82, 0x70, 0x77, 0xEB,
+ 0x77, 0x9B, 0x6C, 0x46, 0x20, 0x27, 0x40, 0xCF,
+ 0xAA, 0xF3, 0x2D, 0xBC, 0xF8, 0xE0, 0xA4, 0x04,
+ 0xAE, 0x72, 0xE7, 0x95, 0x38, 0xA2, 0xAA, 0x45,
+ 0x7F, 0xDB, 0x72, 0x58, 0x0C, 0x30, 0x70, 0x4E,
+ 0x8A, 0xE2, 0xDD, 0x2D, 0xA8, 0x03, 0x9A, 0xEB,
+ 0x99, 0x96, 0x8E, 0x9E, 0xC1, 0x65, 0x8C, 0xB9,
+ 0xD1, 0xE1, 0xED, 0xEC, 0x3C, 0x3F, 0xA8, 0xAB,
+ 0x54, 0x81, 0x2C, 0x16, 0x77, 0x3B, 0x6A, 0xB9,
+ 0x09, 0x51, 0xF0, 0x98, 0x38, 0xF3, 0x69, 0xC6,
+ 0x07, 0xB6, 0x98, 0x2C, 0x00, 0xDA, 0xFF, 0xD4,
+ 0x4B, 0x51, 0x00, 0xF4, 0xF4, 0xC6, 0x59, 0xFF,
+ 0x4D, 0x2F, 0xF0, 0x55, 0x91, 0x33, 0x58, 0xAC,
+ 0x0B, 0xA7, 0x43, 0x4B, 0x11, 0xDA, 0x6F, 0x3A,
+ 0x7A, 0xF1, 0xE5, 0xE4, 0x58, 0xB0, 0xA3, 0x5D,
+ 0x89, 0xDD, 0x6B, 0x84, 0x28, 0x04, 0x1E, 0x0B,
+ 0xD5, 0x3F, 0x5E, 0x87, 0x47, 0xE5, 0xCC, 0xCC,
+ 0xF8, 0x46, 0xD0, 0x41, 0xD4, 0x89, 0xC6, 0x31,
+ 0x4B, 0x9B, 0xF6, 0x64, 0xCB, 0xDE, 0x11, 0x36,
+ 0x7F, 0x1C, 0xC4, 0x4A, 0x10, 0xA0, 0xF0, 0xE2,
+ 0xA8, 0x9D, 0x80, 0x22, 0xAF, 0xFA, 0x1D, 0xCB,
+ 0x99, 0x08, 0x56, 0x12, 0x0C, 0xE8, 0x23, 0xF9,
+ 0x13, 0x68, 0x7C, 0x89, 0x5A, 0xAC, 0x00, 0x25,
+ 0x0A, 0xEF, 0xDD, 0xF1, 0xF4, 0xDC, 0xC1, 0x92,
+ 0x71, 0x12, 0xF2, 0xBF, 0x7F, 0xA9, 0x30, 0x5C,
+ 0x75, 0x43, 0x4F, 0x19, 0x7C, 0xD6, 0x39, 0xF2,
+ 0xDC, 0xAB, 0xE7, 0x36, 0x75, 0x26, 0x2C, 0xC5,
+ 0x4D, 0xBF, 0xD0, 0x4A, 0x20, 0x26, 0x50, 0x9A,
+ 0x31, 0x41, 0x29, 0xD0, 0x73, 0x53, 0x7A, 0x81,
+ 0xF4, 0x5D, 0xDB, 0x8E,
+
+ 0x21, 0x55, 0x95, 0x56, 0x2A, 0xFA, 0x88, 0x2E,
+ 0xC9, 0x9B, 0x1E, 0xE9, 0xA4, 0x4C, 0x1A, 0xC7,
+ 0xFB, 0xF6, 0xA5, 0xE8, 0x5A, 0xFB, 0xF6, 0x53,
+ 0x4C, 0xCD, 0x0F, 0xE7, 0x0A, 0x97, 0x73, 0x95,
+ 0x7C, 0x0E, 0x11, 0x82, 0x07, 0x8F, 0x77, 0x2B,
+ 0xDE, 0x4D, 0x95, 0xDB, 0x27, 0x6D, 0x70, 0x89,
+ 0xC8, 0x5C, 0x1B, 0xC8, 0xEE, 0xEE, 0x8E, 0x75,
+ 0xDB, 0x1B, 0x5E, 0xF2, 0x1D, 0x6D, 0xD8, 0x8C,
+ 0x81, 0x3B, 0x58, 0x71, 0xBA, 0x12, 0x70, 0x12,
+ 0x6E, 0x8D, 0x13, 0x2E, 0x4B, 0x4A, 0x81, 0x93,
+ 0xA9, 0xAD, 0xA6, 0xB2, 0xB2, 0x4D, 0xE2, 0x26,
+ 0x2E, 0xC7, 0x31, 0xD1, 0xFB, 0x02, 0xAB, 0xE9,
+ 0x76, 0xBF, 0x84, 0xEF, 0xE2, 0x02, 0xDA, 0xDE,
+ 0x93, 0x08, 0x3F, 0x02, 0x37, 0x04, 0xC3, 0x37,
+ 0xB0, 0x5B, 0x7F, 0x04, 0x37, 0xC0, 0xA3, 0x67,
+ 0x3F, 0xFA, 0x31, 0x43, 0x10, 0x27, 0xA1, 0x36,
+ 0x3D, 0x56, 0xF9, 0x70, 0xDF, 0x6B, 0x51, 0x61,
+ 0x76, 0xD2, 0x22, 0xCC, 0x19, 0x66, 0x30, 0x63,
+ 0xBC, 0x25, 0x7A, 0x7E, 0x8B, 0x7B, 0x9D, 0xD7,
+ 0x49, 0x99, 0x67, 0x8C, 0x19, 0x2F, 0x51, 0x0F,
+ 0x01, 0xD7, 0x35, 0xF0, 0xA2, 0x20, 0x38, 0x03,
+ 0x9F, 0xCB, 0x42, 0x65, 0xC3, 0x6A, 0x0E, 0xA8,
+ 0xF6, 0x4F, 0xBF, 0x73, 0x3A, 0x1A, 0xDF, 0x48,
+ 0x03, 0x72, 0xF5, 0xB9, 0x94, 0x56, 0xD4, 0x46,
+ 0x93, 0xDD, 0x6B, 0xB3, 0xF9, 0x6B, 0xDF, 0xEC,
+ 0x88, 0x34, 0x6D, 0x39, 0x51, 0xEE, 0xFD, 0xA6,
+ 0x4B, 0xC7, 0x2B, 0xAE, 0xC6, 0x2A, 0x14, 0x15,
+ 0xDF, 0xB3, 0x7E, 0x02, 0x1C, 0x8D, 0xA8, 0xD4,
+ 0xDB, 0x19, 0xCF, 0x19, 0xEA, 0x8A, 0x14, 0xBC,
+ 0x67, 0xB1, 0x62, 0x35, 0x69, 0x84, 0x21, 0x08,
+ 0xF8, 0x5D, 0x44, 0x10, 0xD9,
+
+ 0x0E, 0xE7, 0x88, 0x5B, 0x12, 0x67, 0xA8, 0x08,
+ 0x53, 0xD1, 0x65, 0x84, 0xE8, 0x9C, 0x12, 0xE3,
+ 0xBA, 0x44, 0x83, 0xA1, 0x1E, 0x73, 0xDE, 0x63,
+ 0x6C, 0xCC, 0xF7, 0xA4, 0x6B, 0xD0, 0x6B, 0xBF,
+ 0x3D, 0xAE, 0x4D, 0xF2, 0xB7, 0xF7, 0xC4, 0x30,
+ 0x2F, 0xB0, 0xEE, 0x09, 0x10, 0x20, 0xE1, 0x77,
+ 0x7B, 0xD4, 0xD1, 0x6B, 0x7F, 0x88, 0xA6, 0xE6,
+ 0x51, 0xD5, 0x4E, 0x9F, 0xFD, 0xFB, 0x1F, 0x4A,
+ 0x7C, 0xA7, 0x99, 0x32, 0x3F, 0x7C, 0xEA, 0xD9,
+ 0x36, 0xD4, 0x2C, 0xE1, 0xE0, 0x84, 0x2E, 0xFE,
+ 0x2A, 0x57, 0xA5, 0x56, 0xBD, 0xD3, 0x16, 0x8F,
+ 0x5A, 0x5A, 0x02, 0x20, 0xF1, 0x1B, 0xF0, 0x96,
+ 0x22, 0xBF, 0x1B, 0x24, 0xA4, 0xD2, 0x5A, 0x35,
+ 0x9E, 0xBA, 0x71, 0xB4, 0x5D, 0x13, 0x19, 0x8D,
+ 0x64, 0x4C, 0x5B, 0x22, 0xAA, 0x0E, 0x87, 0x1E,
+ 0xF6, 0x62, 0x8A, 0x94, 0xA6, 0x36, 0x03, 0xEA,
+ 0x6F, 0xB4, 0xFC, 0xA5, 0xC9, 0x98, 0x73, 0x54,
+ 0x38, 0x97, 0x6D, 0xC8, 0x08, 0x01, 0xCA, 0xD8,
+ 0x88, 0xE7, 0xAA, 0x9E, 0xCE, 0x3B, 0xA7, 0xBA,
+ 0x69, 0x50, 0xAB, 0x78, 0x9C, 0x83, 0x20, 0x23,
+ 0x31, 0x1C, 0xCC, 0x01, 0x52, 0xDF, 0x6F, 0xC2,
+ 0x56, 0x09, 0x57, 0xFF, 0xDE, 0x27, 0xD4, 0x17,
+ 0x4E, 0x6B, 0xD5, 0x60, 0x3A, 0x9F, 0xC8, 0xA4,
+ 0x1A, 0xAB, 0x82, 0x9A, 0x05, 0x15, 0xC8, 0x66,
+ 0x89, 0x40, 0x2A, 0x90, 0xF8, 0xEB, 0xD1, 0x2F,
+ 0x6E, 0x68, 0x13, 0xAD, 0x66, 0x39, 0x6C, 0xB1,
+ 0x7C, 0xEE, 0x33, 0xB7, 0xA6, 0x88, 0x69, 0xE1,
+ 0x32, 0x34, 0xA4, 0x87, 0xB1, 0x0C, 0xF3, 0x59,
+ 0xBE, 0x88, 0x72, 0x77, 0x76, 0x61, 0x45, 0x6F,
+ 0xF7, 0x75, 0x12, 0xB6, 0x03, 0x17, 0xE9, 0x2E,
+ 0x15, 0x93, 0xDA, 0xA9, 0xAE, 0x12,
+
+ 0x4E, 0xB8, 0x67, 0xB1, 0x3C, 0x12, 0xCD, 0x1E,
+ 0x2D, 0xA3, 0x9C, 0xE5, 0xA6, 0x4A, 0x08, 0x0E,
+ 0x0D, 0x1C, 0x9B, 0xE7, 0xE5, 0x6D, 0x0A, 0x75,
+ 0xE0, 0xE4, 0x33, 0x3B, 0x43, 0x3D, 0x2C, 0x39,
+ 0x96, 0x43, 0x8F, 0xF6, 0xA4, 0xAA, 0x5E, 0x32,
+ 0xFE, 0x00, 0xCD, 0xD6, 0x9D, 0x75, 0x6F, 0x3A,
+ 0x20, 0x4E, 0x05, 0xB5, 0x7C, 0xE8, 0xDA, 0xE1,
+ 0x32, 0x10, 0xC0, 0x85, 0x8D, 0x34, 0x35, 0x12,
+ 0x41, 0x50, 0xBF, 0x58, 0xB8, 0xFF, 0x4E, 0x6B,
+ 0x04, 0x40, 0x76, 0xAD, 0xCC, 0x31, 0xDB, 0xF4,
+ 0x12, 0x7F, 0x30, 0x4E, 0x28, 0x28, 0x73, 0x67,
+ 0xED, 0x35, 0x38, 0x18, 0xD9, 0x9D, 0xEA, 0x68,
+ 0xFA, 0x65, 0x28, 0x7B, 0x99, 0x3A, 0x89, 0x7D,
+ 0x52, 0xE1, 0x59, 0x4C, 0x68, 0xC9, 0xDA, 0xFC,
+ 0x3D, 0x39, 0xE0, 0x81, 0xDB, 0x22, 0xBD, 0xBF,
+ 0xF3, 0xDA, 0x45, 0x1D, 0x3A, 0x8D, 0xF3, 0x97,
+ 0x9E, 0xDA, 0x2A, 0xD5, 0x4E, 0x2C, 0x23, 0x74,
+ 0x3A, 0xC9, 0x73, 0x4D, 0x24, 0x7E, 0x1A, 0x9B,
+ 0xF9, 0xD7, 0x21, 0x4D, 0x9A, 0x28, 0x21, 0x44,
+ 0xD4, 0xE8, 0x93, 0xC5, 0x4F, 0x9A, 0xF9, 0x66,
+ 0x09, 0xA5, 0x46, 0x31, 0x59, 0xB3, 0xCC, 0xF3,
+ 0xD4, 0x58, 0x9E, 0x8E, 0xB5, 0x35, 0x47, 0x5C,
+ 0x23, 0xC9, 0xFC, 0xE8, 0x64, 0x5D, 0x47, 0x6C,
+ 0x43, 0xAC, 0x47, 0x30, 0xAE, 0x40, 0x7A, 0x9E,
+ 0x1F, 0xF9, 0x74, 0x55, 0x10, 0x6F, 0x2A, 0xEB,
+ 0x50, 0x63, 0x51, 0xDD, 0x8E, 0x38, 0x6F, 0x27,
+ 0x1F, 0x21, 0x3C, 0xDC, 0x65, 0x63, 0xE4, 0xE8,
+ 0xD8, 0x63, 0x20, 0x67, 0x96, 0x22, 0xFD, 0xC3,
+ 0xA0, 0xDB, 0x90, 0x64, 0x56, 0xE6, 0xB0, 0xFE,
+ 0xB3, 0x7C, 0x74, 0x2C, 0x01, 0xD5, 0xCC, 0xD4,
+ 0x3C, 0x1B, 0xBA, 0x79, 0x68, 0x33, 0x7C,
+
+ 0x3E, 0x82, 0xD7, 0x53, 0xF6, 0x16, 0xE3, 0x10,
+ 0x01, 0x36, 0xA8, 0xEF, 0x33, 0xCA, 0x26, 0xC9,
+ 0x21, 0xBF, 0xCA, 0x3B, 0x7D, 0x89, 0xC2, 0x59,
+ 0x1D, 0x57, 0x2B, 0x02, 0x05, 0xEA, 0x49, 0x99,
+ 0x31, 0x95, 0xFF, 0x0A, 0x45, 0x56, 0x1D, 0xB9,
+ 0xD3, 0x01, 0x44, 0xC4, 0x8C, 0x88, 0xAD, 0xC9,
+ 0x83, 0x6A, 0x35, 0x83, 0x81, 0xBC, 0x59, 0x0A,
+ 0xB0, 0x2A, 0x82, 0xE5, 0x89, 0x54, 0xA0, 0xAC,
+ 0x69, 0x1A, 0x63, 0x5B, 0x2C, 0x8A, 0x61, 0xAE,
+ 0x72, 0xD9, 0xDB, 0xF0, 0x6C, 0xAA, 0x8F, 0x61,
+ 0x46, 0x0C, 0x0A, 0x5D, 0xE6, 0x15, 0x92, 0x65,
+ 0x83, 0xCF, 0x80, 0xB6, 0x78, 0x9E, 0x87, 0x9B,
+ 0x13, 0xD5, 0x94, 0xD2, 0x1E, 0x7A, 0x28, 0x8B,
+ 0x14, 0x76, 0x0C, 0x7E, 0x41, 0xAE, 0x5B, 0x36,
+ 0x40, 0xD9, 0x30, 0x31, 0xFD, 0x73, 0x81, 0xCC,
+ 0x83, 0x22, 0x03, 0xFF, 0xB6, 0xCC, 0xFA, 0xD7,
+ 0x3A, 0x1C, 0xB4, 0xA8, 0x48, 0x47, 0xD9, 0xA9,
+ 0x54, 0xCE, 0x26, 0x92, 0x84, 0x19, 0x6D, 0x57,
+ 0x1B, 0x24, 0x3B, 0x5F, 0xBD, 0xBB, 0x7F, 0x18,
+ 0x97, 0xE2, 0x79, 0x81, 0x7B, 0x19, 0xB6, 0x9C,
+ 0x4F, 0xE6, 0xD5, 0x01, 0x8B, 0x41, 0xE5, 0x21,
+ 0x18, 0x76, 0x2A, 0x16, 0xC2, 0xEF, 0x20, 0xAC,
+ 0xB0, 0x0E, 0x58, 0x8C, 0x6D, 0xE7, 0x02, 0x35,
+ 0x15, 0x94, 0xDB, 0xC6, 0x58, 0xE3, 0xF0, 0x0F,
+ 0xBF, 0x6A, 0x63, 0xE0, 0x4A, 0x51, 0x32, 0x90,
+ 0x40, 0x84, 0xB6, 0x05, 0x92, 0xB1, 0x6B, 0xF8,
+ 0xCD, 0xCD, 0x7F, 0xF1, 0x43, 0x72, 0xBB, 0x8B,
+ 0x1E, 0xAF, 0xE5, 0x78, 0x75, 0x72, 0xE5, 0x72,
+ 0x14, 0x2D, 0x5B, 0x83, 0xD2, 0x40, 0x55, 0xFC,
+ 0x8C, 0x9B, 0xFB, 0xAE, 0xCC, 0x51, 0xBE, 0x56,
+ 0x9D, 0x4C, 0xC1, 0xFC, 0xF1, 0xC3, 0xC3, 0xAD,
+
+ 0xA9, 0x2F, 0xB7, 0xB1, 0x24, 0x2E, 0xD1, 0x6E,
+ 0xAF, 0x5B, 0xC5, 0xF2, 0xF8, 0x5E, 0x43, 0x83,
+ 0xB4, 0x3D, 0x57, 0xD6, 0x16, 0x8D, 0x56, 0x31,
+ 0xE5, 0xEB, 0x44, 0x01, 0x9F, 0xCA, 0x6E, 0x77,
+ 0xC2, 0xAC, 0xAD, 0x84, 0x1E, 0x4B, 0x38, 0xCC,
+ 0x48, 0x36, 0xD6, 0x8E, 0xCA, 0xAD, 0x67, 0x3E,
+ 0x20, 0xD2, 0x3A, 0x84, 0xA2, 0x79, 0x60, 0xBD,
+ 0xA2, 0x1B, 0x7E, 0x41, 0x57, 0x2D, 0x52, 0x41,
+ 0x41, 0x1C, 0x32, 0x5F, 0xE4, 0x1B, 0x21, 0x55,
+ 0xA9, 0xAE, 0xFE, 0xB1, 0x80, 0xB2, 0x85, 0x0E,
+ 0x5A, 0xA8, 0x06, 0x4C, 0x73, 0x96, 0xC7, 0xDF,
+ 0x39, 0x6D, 0x5A, 0x69, 0x7F, 0x3C, 0xC1, 0x71,
+ 0xEF, 0xEC, 0x84, 0x23, 0x5F, 0x92, 0xD9, 0x07,
+ 0x2D, 0x73, 0x4A, 0xAB, 0x55, 0x46, 0xE8, 0xCC,
+ 0x46, 0x2C, 0x09, 0x7B, 0x65, 0xD7, 0xCF, 0x1A,
+ 0x3B, 0x27, 0xD3, 0x8C, 0x3B, 0x8A, 0xDC, 0xDB,
+ 0x36, 0x95, 0x06, 0x8D, 0x5B, 0x44, 0xBA, 0xBF,
+ 0x7E, 0x50, 0xAF, 0xC3, 0x63, 0x66, 0xB9, 0xD3,
+ 0xB0, 0xC4, 0x2C, 0x03, 0xBF, 0x7E, 0x70, 0xCF,
+ 0x93, 0xEB, 0x3D, 0xDC, 0x74, 0x16, 0x49, 0x0A,
+ 0x02, 0x98, 0x4F, 0x81, 0x6C, 0x29, 0x53, 0x39,
+ 0x25, 0xBA, 0xD4, 0x59, 0xF2, 0xB9, 0x92, 0xE6,
+ 0x83, 0x41, 0xE2, 0x7B, 0xE1, 0x6E, 0xA0, 0x8F,
+ 0xC4, 0xE8, 0x35, 0x76, 0x5A, 0x3A, 0xA4, 0x35,
+ 0x83, 0x85, 0x77, 0xA9, 0x63, 0x00, 0xA1, 0x29,
+ 0xD5, 0x43, 0x05, 0x59, 0xA3, 0x52, 0x3E, 0xE4,
+ 0xDA, 0xC1, 0x72, 0x36, 0x8F, 0x5E, 0xA0, 0x8B,
+ 0x88, 0x3D, 0xE9, 0x19, 0x11, 0x89, 0x3F, 0x0E,
+ 0xF1, 0x04, 0xA9, 0x4C, 0x87, 0xFF, 0x08, 0x89,
+ 0xF9, 0x13, 0xEB, 0xE7, 0x28, 0x41, 0x0B, 0x58,
+ 0xA4, 0xA9, 0x19, 0xC7, 0x4F, 0x34, 0xFD, 0x54,
+ 0x0A,
+
+ 0x79, 0x14, 0x36, 0xA5, 0x6B, 0x3F, 0x22, 0xFA,
+ 0x12, 0x4B, 0x4F, 0xC4, 0x97, 0xD7, 0xC7, 0x61,
+ 0x94, 0x53, 0x53, 0xD3, 0xF5, 0x07, 0x64, 0x7D,
+ 0xE0, 0x11, 0x63, 0xC5, 0xE7, 0x4A, 0x88, 0xEC,
+ 0x6C, 0x0D, 0xA5, 0x05, 0x13, 0xE4, 0xC6, 0x94,
+ 0x3D, 0xEE, 0x87, 0xB1, 0x77, 0xCE, 0xB6, 0x7E,
+ 0xC9, 0x99, 0xB5, 0xAA, 0xB2, 0xC8, 0x0F, 0x5F,
+ 0xE9, 0x92, 0x9F, 0x1E, 0x49, 0x6D, 0xC8, 0xD7,
+ 0x6D, 0x1E, 0xD7, 0x63, 0x6D, 0xDD, 0x64, 0xCB,
+ 0xFF, 0x45, 0xB0, 0xF6, 0x89, 0xC5, 0xF3, 0xFB,
+ 0x82, 0xB9, 0x5B, 0xF1, 0x42, 0x4A, 0x8C, 0x9E,
+ 0xCD, 0x9D, 0xEF, 0x9D, 0x36, 0x79, 0x04, 0x7D,
+ 0x16, 0x6D, 0xC6, 0x66, 0xAA, 0xFE, 0x1D, 0xAB,
+ 0x4D, 0xDF, 0xF8, 0xE8, 0xC3, 0x12, 0xB3, 0xAD,
+ 0x49, 0xD1, 0x85, 0x7D, 0x2C, 0x76, 0xD9, 0x66,
+ 0x85, 0xA0, 0x81, 0x29, 0x2B, 0x13, 0x47, 0x1E,
+ 0x98, 0x77, 0x79, 0x3F, 0x23, 0xD2, 0xFC, 0xA5,
+ 0xA5, 0x64, 0xDF, 0xBB, 0x3E, 0xA8, 0x85, 0x98,
+ 0xB1, 0x34, 0x2B, 0xB7, 0xA0, 0xD1, 0x7A, 0x47,
+ 0x42, 0xFE, 0x98, 0x80, 0xBB, 0x21, 0x19, 0x4F,
+ 0xE0, 0x58, 0x2D, 0xD9, 0xE2, 0x0F, 0x46, 0x13,
+ 0xC7, 0x4A, 0x11, 0xDD, 0x49, 0xEC, 0x32, 0x0C,
+ 0x1C, 0x3C, 0x96, 0x75, 0x3C, 0xB4, 0x73, 0x07,
+ 0x3E, 0xBC, 0xA4, 0xB8, 0x17, 0x05, 0x38, 0x92,
+ 0x6B, 0x56, 0xF3, 0x28, 0xE3, 0x71, 0x73, 0x2A,
+ 0x30, 0x4C, 0xF5, 0xCF, 0x2A, 0xC5, 0x1B, 0x24,
+ 0x4E, 0xA0, 0x2C, 0x9A, 0xCA, 0x98, 0x8C, 0xCA,
+ 0x16, 0xD3, 0xA6, 0x77, 0xC7, 0x83, 0x3C, 0x25,
+ 0x96, 0x0D, 0x15, 0xBE, 0x33, 0x7E, 0xCA, 0x3A,
+ 0xC0, 0x37, 0x7C, 0x91, 0x04, 0xF0, 0x4D, 0x8D,
+ 0xAE, 0xBF, 0x6B, 0x99, 0x57, 0x63, 0x90, 0x10,
+ 0x41, 0xF1,
+
+ 0x83, 0xD6, 0xF5, 0x41, 0x9F, 0x3B, 0x2C, 0x9B,
+ 0xAB, 0xAF, 0x1B, 0xAE, 0x69, 0xB4, 0xAA, 0x5B,
+ 0xF9, 0x5F, 0x0F, 0xC7, 0xD4, 0x7F, 0x90, 0xAF,
+ 0xB2, 0xBA, 0xAB, 0x86, 0x92, 0x8E, 0x66, 0x46,
+ 0xD5, 0x73, 0x08, 0xB7, 0x3E, 0x46, 0x86, 0xC0,
+ 0x1C, 0x72, 0xB1, 0xDF, 0x7A, 0x3A, 0xC4, 0xEF,
+ 0x85, 0x36, 0x21, 0x3C, 0x29, 0xB9, 0x68, 0xFD,
+ 0x48, 0xBD, 0x1A, 0x5C, 0x83, 0xA3, 0x02, 0xFD,
+ 0x67, 0xBF, 0xC3, 0xD1, 0x68, 0xE1, 0xB8, 0x91,
+ 0x57, 0xA5, 0x7B, 0xE8, 0x4B, 0x82, 0x7C, 0x76,
+ 0xEB, 0x1C, 0x38, 0x4C, 0x1E, 0x54, 0xE8, 0x66,
+ 0x47, 0x47, 0x8A, 0x41, 0xD7, 0x38, 0xCC, 0x8E,
+ 0xD8, 0x58, 0x20, 0x26, 0x79, 0x7B, 0x5A, 0xCF,
+ 0xD0, 0x0E, 0x6C, 0xE4, 0x91, 0x01, 0xE4, 0x95,
+ 0xF8, 0x6D, 0x7F, 0xFD, 0x38, 0x04, 0x41, 0x23,
+ 0x72, 0xC7, 0x32, 0xD9, 0x65, 0x4F, 0xCF, 0x3D,
+ 0xE8, 0xA3, 0xA7, 0x9C, 0xEF, 0x05, 0xDE, 0x12,
+ 0x70, 0x96, 0x04, 0x2C, 0x75, 0x06, 0xBE, 0xEC,
+ 0xA0, 0x37, 0x43, 0xF7, 0x39, 0x7E, 0x90, 0x39,
+ 0xAB, 0xFF, 0x97, 0x27, 0x05, 0xBC, 0x9D, 0xB9,
+ 0xDB, 0x8C, 0xFB, 0x10, 0x55, 0xC1, 0x63, 0xAA,
+ 0x59, 0xD3, 0x09, 0xC7, 0x49, 0xDB, 0x18, 0x2B,
+ 0x4A, 0xAE, 0x2B, 0x0E, 0xE0, 0x45, 0x3E, 0x96,
+ 0xF8, 0x82, 0x0F, 0xC4, 0xB7, 0x17, 0x3A, 0x0B,
+ 0x1D, 0x43, 0x81, 0x33, 0xA5, 0xDD, 0x26, 0x12,
+ 0xBF, 0xD9, 0x56, 0x13, 0xD8, 0xBB, 0xBE, 0xA8,
+ 0xAE, 0xCE, 0xF0, 0x99, 0x95, 0x66, 0xA0, 0xB5,
+ 0xD1, 0x94, 0xA3, 0xF8, 0x42, 0x3F, 0x3B, 0x0F,
+ 0x56, 0x9A, 0xBF, 0xAE, 0xEE, 0xC1, 0xA8, 0x25,
+ 0xFA, 0xF5, 0x0D, 0xAE, 0x4F, 0x40, 0x2B, 0xB2,
+ 0xEF, 0xB1, 0x61, 0xCF, 0x41, 0x6D, 0x96, 0x4D,
+ 0x8E, 0x0B, 0xFE,
+
+ 0x24, 0xE7, 0xE5, 0x6C, 0xA2, 0x9D, 0xFB, 0xD1,
+ 0x90, 0xAA, 0xF0, 0xE7, 0xA6, 0x08, 0x5C, 0x80,
+ 0x69, 0xEE, 0x83, 0xE9, 0x8B, 0x70, 0x0B, 0x97,
+ 0xFB, 0xF0, 0xE5, 0x43, 0x81, 0x6D, 0xDC, 0xE9,
+ 0x4C, 0x14, 0xFA, 0xEA, 0x1F, 0x39, 0x31, 0x2A,
+ 0x60, 0x87, 0x10, 0x95, 0x19, 0x3A, 0x97, 0x09,
+ 0xF6, 0x7A, 0xDF, 0xF1, 0xAE, 0xB5, 0x43, 0x0D,
+ 0x6C, 0x1E, 0x2C, 0xC9, 0x2A, 0xF3, 0x76, 0xDA,
+ 0x6A, 0xEB, 0xE4, 0x92, 0x74, 0x82, 0xF1, 0x4C,
+ 0x64, 0x28, 0x01, 0xB0, 0xE1, 0xDF, 0x9A, 0x6B,
+ 0x89, 0x02, 0xE0, 0x43, 0xC6, 0x77, 0x18, 0xE8,
+ 0xC4, 0xC9, 0x98, 0xF2, 0x8F, 0xE0, 0xB4, 0x38,
+ 0x50, 0x81, 0xC7, 0xF4, 0x3F, 0xE2, 0xD9, 0xCB,
+ 0x5E, 0xE9, 0x5B, 0xC5, 0x98, 0xD2, 0xEB, 0xC6,
+ 0x13, 0x3E, 0xC1, 0x13, 0xFD, 0x54, 0x48, 0xA0,
+ 0x09, 0x64, 0x71, 0xE5, 0xCA, 0xC0, 0x75, 0x2D,
+ 0xF7, 0x89, 0x5B, 0x00, 0x05, 0xE1, 0x4B, 0xA8,
+ 0xDA, 0x12, 0x6A, 0x4E, 0xCE, 0xAB, 0x3A, 0xDF,
+ 0x4A, 0x90, 0xF4, 0xCA, 0x6C, 0x40, 0x00, 0xF9,
+ 0x9F, 0x92, 0xF7, 0x94, 0x53, 0x77, 0x55, 0x7F,
+ 0xA8, 0xA5, 0xBC, 0xC2, 0xC2, 0x45, 0xBB, 0x07,
+ 0x13, 0x4D, 0x9E, 0x0D, 0xCF, 0x49, 0xF1, 0x5A,
+ 0x69, 0xDF, 0x2D, 0x53, 0x54, 0xB7, 0x7A, 0xD4,
+ 0x2F, 0x1B, 0x99, 0x78, 0x84, 0x81, 0x04, 0xC4,
+ 0x5C, 0x26, 0x35, 0x01, 0xED, 0x75, 0xBC, 0x54,
+ 0x71, 0xA3, 0x96, 0x9E, 0xD4, 0x41, 0xCB, 0x05,
+ 0xB3, 0x08, 0x98, 0xAD, 0x93, 0x15, 0xF7, 0xC2,
+ 0xF4, 0xCB, 0xE6, 0xB7, 0xEB, 0x3F, 0xF7, 0x62,
+ 0x45, 0x40, 0xE3, 0x97, 0x58, 0xC4, 0x49, 0xED,
+ 0xBA, 0x92, 0xA3, 0x94, 0x1F, 0xCD, 0x66, 0x9C,
+ 0xA6, 0x85, 0x1F, 0xBF, 0xA1, 0xAA, 0x03, 0x1B,
+ 0xB2, 0x70, 0x9D, 0xE3,
+
+ 0x0B, 0x45, 0xA1, 0x98, 0x47, 0xD8, 0xB2, 0x5D,
+ 0x41, 0xA7, 0x35, 0xE4, 0x41, 0x4B, 0x45, 0x6A,
+ 0x9A, 0x91, 0xA5, 0x66, 0xDA, 0x63, 0xE7, 0xB8,
+ 0x4E, 0x88, 0x0A, 0x80, 0x2E, 0xEC, 0x08, 0x74,
+ 0x8E, 0xEB, 0xDA, 0xC4, 0x6D, 0xB5, 0xDA, 0x27,
+ 0xEC, 0x67, 0xAC, 0x7D, 0x63, 0x7A, 0xF4, 0x9B,
+ 0xB6, 0x43, 0xE5, 0x87, 0xA7, 0x52, 0x34, 0xFD,
+ 0x15, 0x99, 0xC7, 0x13, 0x3E, 0xC6, 0x4F, 0x38,
+ 0xA3, 0x8B, 0xD1, 0xB4, 0x5E, 0x0E, 0xC0, 0xA8,
+ 0x9B, 0x34, 0x47, 0xC3, 0x61, 0x82, 0x0D, 0xBF,
+ 0x78, 0x2F, 0x90, 0x7B, 0x07, 0x5A, 0x2B, 0xA2,
+ 0xB6, 0x9D, 0xB0, 0x15, 0x0A, 0x32, 0xA1, 0x70,
+ 0x4E, 0x8D, 0x98, 0xC4, 0xB7, 0xE0, 0xD0, 0xBE,
+ 0x1D, 0xB4, 0xA3, 0xC9, 0x6A, 0xA4, 0xE6, 0x4F,
+ 0x12, 0xC2, 0x35, 0xD7, 0xA6, 0x69, 0x67, 0x18,
+ 0x2C, 0xB0, 0xCF, 0x39, 0x78, 0xDB, 0xB7, 0x66,
+ 0x50, 0xFD, 0xB7, 0x3F, 0x77, 0x7F, 0x4E, 0x3C,
+ 0xF8, 0xBD, 0xC5, 0xD2, 0xCA, 0xCB, 0xCB, 0x10,
+ 0x94, 0x9F, 0x3E, 0xA0, 0x5B, 0xBA, 0x74, 0xB9,
+ 0x84, 0xFE, 0xB1, 0x91, 0x93, 0x5D, 0x8B, 0x23,
+ 0x86, 0x8F, 0xCB, 0xF0, 0x0E, 0x27, 0xA8, 0x6A,
+ 0x57, 0xF3, 0x7A, 0xEE, 0x94, 0x5F, 0x29, 0x3F,
+ 0xF8, 0xD3, 0xD1, 0x30, 0xCD, 0x8B, 0x31, 0xFC,
+ 0x6E, 0xC6, 0x31, 0xB7, 0x76, 0x26, 0x12, 0x7A,
+ 0xB9, 0xB0, 0x29, 0x4D, 0xAF, 0x10, 0xFC, 0xCC,
+ 0xD1, 0xD6, 0x9C, 0x19, 0x81, 0x15, 0xC4, 0x19,
+ 0xDD, 0x5D, 0x56, 0x65, 0x6C, 0xE0, 0x39, 0x25,
+ 0x5C, 0xE5, 0xE2, 0x6E, 0x5D, 0x48, 0x44, 0xF8,
+ 0x53, 0x4A, 0x36, 0x48, 0xDB, 0x0D, 0x89, 0xF7,
+ 0x1B, 0xF5, 0xD0, 0x8E, 0xA2, 0xD8, 0xD7, 0x9E,
+ 0xCE, 0x35, 0xA0, 0x10, 0xE5, 0xBC, 0x22, 0xF9,
+ 0xC3, 0x35, 0xEC, 0x35, 0x6C,
+
+ 0x59, 0x77, 0x61, 0xB9, 0xD2, 0xA0, 0x7C, 0xD6,
+ 0x95, 0x93, 0x17, 0x1B, 0x25, 0x09, 0x47, 0xF1,
+ 0x1B, 0x73, 0x28, 0xA8, 0xA1, 0xF6, 0x0F, 0x7F,
+ 0x4B, 0x86, 0xED, 0xC5, 0xBD, 0x15, 0x92, 0x75,
+ 0x23, 0x3E, 0x38, 0x30, 0xE0, 0x64, 0x80, 0x7B,
+ 0x10, 0xD5, 0x54, 0x08, 0x6E, 0x3D, 0x78, 0xFE,
+ 0x40, 0x0C, 0xFD, 0x86, 0xC1, 0xD1, 0xD4, 0xE7,
+ 0xF0, 0xD2, 0xFF, 0x52, 0xA4, 0x8F, 0xA8, 0x0A,
+ 0x9C, 0x6E, 0x49, 0x70, 0xC6, 0x7D, 0x7C, 0xDD,
+ 0xCE, 0x75, 0x09, 0xE3, 0xBF, 0x5A, 0x4A, 0x30,
+ 0xFD, 0xC0, 0x2B, 0x8F, 0x23, 0x39, 0x6B, 0x41,
+ 0x17, 0x51, 0x1F, 0x16, 0xAC, 0x33, 0x69, 0x42,
+ 0xD2, 0xE2, 0x32, 0x91, 0x81, 0xCB, 0x7C, 0x04,
+ 0xC8, 0xD9, 0x77, 0x1A, 0x59, 0xC7, 0x37, 0x5C,
+ 0x5B, 0xC3, 0x9F, 0x22, 0xE5, 0xDA, 0xD8, 0x59,
+ 0x3C, 0x01, 0xE6, 0xCC, 0x46, 0x5C, 0x90, 0xE0,
+ 0x3F, 0x4D, 0x77, 0xAD, 0x96, 0x2A, 0x5D, 0x37,
+ 0x0F, 0x59, 0x10, 0xF0, 0x23, 0xF0, 0xA9, 0x75,
+ 0xED, 0xDE, 0xFB, 0x74, 0x06, 0x2B, 0xBF, 0x20,
+ 0xED, 0xEA, 0xCD, 0x49, 0x8A, 0x41, 0x09, 0x6C,
+ 0x0F, 0x0E, 0x79, 0xF7, 0x61, 0x18, 0xBF, 0x77,
+ 0x09, 0xB9, 0x05, 0xEF, 0x89, 0xEE, 0x79, 0xD9,
+ 0x20, 0xAF, 0xE3, 0x3F, 0x0E, 0xCE, 0x3E, 0x94,
+ 0x0C, 0x3B, 0xC1, 0xA0, 0x88, 0xA8, 0x8D, 0xDB,
+ 0x4D, 0x70, 0xC6, 0x19, 0x2A, 0xCE, 0xE1, 0x9D,
+ 0x9E, 0x60, 0xBD, 0x93, 0x2D, 0xF1, 0xC6, 0x50,
+ 0x1B, 0xA7, 0x21, 0x7B, 0x11, 0x86, 0xCD, 0xF9,
+ 0x17, 0xAE, 0x4B, 0x88, 0x7B, 0xAF, 0xD1, 0xCA,
+ 0x80, 0xF7, 0xA1, 0x7F, 0x0A, 0x4D, 0xF8, 0x35,
+ 0x6E, 0xB1, 0x61, 0xEC, 0xAB, 0xD7, 0x60, 0x2D,
+ 0xB8, 0xB7, 0x59, 0x77, 0x90, 0xED, 0xC5, 0x24,
+ 0xCA, 0x02, 0xF2, 0x35, 0xD8, 0xB4,
+
+ 0xE5, 0x07, 0x55, 0x53, 0x6C, 0x5E, 0xD2, 0x9F,
+ 0xE4, 0x23, 0xA5, 0x58, 0x45, 0x18, 0x2B, 0x0B,
+ 0x17, 0x00, 0xE8, 0xD7, 0x89, 0x06, 0xE6, 0x75,
+ 0x56, 0x25, 0xC0, 0x92, 0x79, 0xCD, 0xA2, 0xC0,
+ 0xBD, 0x8E, 0x52, 0x0D, 0xF3, 0xA2, 0xA1, 0x66,
+ 0x0F, 0x94, 0x23, 0xE7, 0x2D, 0x14, 0xB6, 0x82,
+ 0xB0, 0x9A, 0xE1, 0xE8, 0xF3, 0x15, 0x92, 0xFB,
+ 0xDE, 0x8D, 0xA2, 0x1A, 0xB3, 0xB2, 0xF7, 0xC0,
+ 0xAB, 0xA9, 0x79, 0x70, 0xBE, 0xE8, 0x14, 0x65,
+ 0x79, 0x10, 0x1C, 0x7C, 0x29, 0x2C, 0x16, 0x33,
+ 0xBB, 0xEF, 0x91, 0x5A, 0xC0, 0xA5, 0x7D, 0x97,
+ 0x79, 0x42, 0xB9, 0xA3, 0x7E, 0x9E, 0x87, 0xBB,
+ 0xDC, 0x65, 0x12, 0xDC, 0xD9, 0x2D, 0x73, 0x8A,
+ 0x73, 0x38, 0xF1, 0xA5, 0x60, 0x7E, 0xD1, 0xF3,
+ 0x97, 0xAB, 0xCF, 0xFF, 0x5C, 0x5E, 0xE1, 0xAC,
+ 0x1A, 0x41, 0xC2, 0x6D, 0xB1, 0x24, 0xAF, 0x19,
+ 0x55, 0x61, 0x4D, 0xDA, 0xD4, 0xE7, 0x10, 0x78,
+ 0x14, 0x2B, 0xA4, 0x88, 0x9D, 0x2F, 0x96, 0xF8,
+ 0x03, 0xF6, 0xB5, 0x13, 0x2B, 0xEA, 0x52, 0x24,
+ 0xB2, 0xA1, 0x46, 0xEC, 0x57, 0x59, 0x19, 0x17,
+ 0x83, 0x05, 0x20, 0x44, 0x4C, 0xEC, 0xC7, 0xE0,
+ 0xB1, 0x84, 0x00, 0x62, 0xE5, 0xE5, 0xAA, 0x0B,
+ 0xE6, 0x0E, 0x44, 0x5D, 0x55, 0x1D, 0x15, 0xDC,
+ 0xCE, 0x53, 0x2C, 0xF9, 0x7B, 0xDE, 0x95, 0x05,
+ 0xAF, 0x88, 0x59, 0xF1, 0xC2, 0x59, 0x3A, 0xFC,
+ 0x2E, 0x43, 0x37, 0x2F, 0xB8, 0x83, 0xD5, 0x42,
+ 0xE3, 0xA2, 0xFC, 0xA1, 0x62, 0xC6, 0x99, 0x9C,
+ 0x4C, 0x7A, 0x72, 0xD6, 0xF5, 0xF8, 0x3E, 0xE1,
+ 0xD0, 0x21, 0xE1, 0x74, 0x69, 0xB4, 0xE5, 0xB5,
+ 0x26, 0x2C, 0x37, 0x73, 0x90, 0xD3, 0x1D, 0x5B,
+ 0x08, 0xF4, 0x64, 0xE4, 0x9F, 0xA1, 0x95, 0xAE,
+ 0xCA, 0xB5, 0x6A, 0xD4, 0x50, 0x12, 0xDC,
+
+ 0xED, 0xE8, 0x53, 0x43, 0xCA, 0x1B, 0xB7, 0x40,
+ 0x82, 0x4A, 0x01, 0x55, 0xD6, 0x0F, 0x9F, 0xFE,
+ 0x2F, 0x1B, 0x94, 0x9F, 0x49, 0xFA, 0x86, 0x45,
+ 0x3C, 0x63, 0x14, 0x2E, 0xAF, 0x66, 0x78, 0x97,
+ 0xA3, 0x40, 0x11, 0x32, 0x52, 0x3F, 0x22, 0x26,
+ 0xCA, 0xCC, 0x61, 0x3F, 0x31, 0x5E, 0x67, 0x5D,
+ 0x71, 0x7D, 0x5F, 0x69, 0xBF, 0xDC, 0x93, 0x1E,
+ 0xA8, 0x5F, 0xA2, 0x56, 0x91, 0xEC, 0xCE, 0x61,
+ 0x67, 0xF3, 0xDC, 0xE8, 0xF4, 0xF7, 0x46, 0xE9,
+ 0xE3, 0xB8, 0x21, 0x2A, 0x6E, 0xB9, 0xDD, 0x69,
+ 0x14, 0xFF, 0x1C, 0xC1, 0xF4, 0x27, 0x6B, 0x6E,
+ 0x2D, 0xC0, 0x75, 0x56, 0xF9, 0x75, 0x21, 0x3D,
+ 0x39, 0xE0, 0x67, 0x3C, 0xCC, 0x4D, 0x95, 0xDD,
+ 0xFE, 0x99, 0x1C, 0x77, 0xA6, 0xF2, 0x62, 0x23,
+ 0x79, 0x49, 0xAB, 0x65, 0x34, 0x2F, 0x71, 0x6F,
+ 0xCD, 0xA3, 0xBF, 0xF3, 0xAE, 0x08, 0xF8, 0xF3,
+ 0x18, 0x67, 0x51, 0x33, 0xD7, 0x3B, 0xF1, 0xD0,
+ 0x37, 0xA9, 0x07, 0x52, 0x77, 0xF0, 0x75, 0x0C,
+ 0xC6, 0x4A, 0xDC, 0x6B, 0x4C, 0xBF, 0x80, 0xEC,
+ 0x42, 0x89, 0x19, 0x22, 0xE1, 0x90, 0x2F, 0xC9,
+ 0x5E, 0x5D, 0xC8, 0xCF, 0xD3, 0x9F, 0x37, 0xAF,
+ 0x60, 0xAE, 0x34, 0x5F, 0xD8, 0x3F, 0xA9, 0x55,
+ 0x0E, 0x5C, 0xC9, 0xA8, 0xA2, 0x0E, 0xE3, 0xC2,
+ 0xAC, 0x9E, 0x87, 0x38, 0xBB, 0x53, 0x86, 0x82,
+ 0xDF, 0x05, 0xE4, 0x23, 0xF3, 0x77, 0xDA, 0x7A,
+ 0x1E, 0x9C, 0x88, 0x53, 0xB9, 0x14, 0x56, 0x49,
+ 0x2F, 0x6A, 0xE8, 0x3A, 0xF1, 0x5C, 0x72, 0xAF,
+ 0x2A, 0x19, 0x0A, 0xBB, 0x2B, 0xFD, 0x91, 0x59,
+ 0x43, 0x12, 0x9C, 0xC3, 0x0B, 0x7A, 0x7F, 0x85,
+ 0x1C, 0x98, 0x34, 0xF6, 0xDE, 0x59, 0x3F, 0x7C,
+ 0x49, 0x37, 0x75, 0x6B, 0xC1, 0xE1, 0xD7, 0x70,
+ 0xB9, 0xFB, 0xCA, 0xD8, 0x41, 0x6B, 0x8C, 0x01,
+
+ 0xB9, 0xC3, 0x0F, 0x35, 0xEB, 0x2F, 0x12, 0x4E,
+ 0xE4, 0x78, 0x2D, 0x24, 0x77, 0xA4, 0x89, 0x1F,
+ 0x64, 0xAD, 0xE7, 0x2B, 0x49, 0xE0, 0xDC, 0x05,
+ 0x7D, 0x6C, 0xEC, 0x4E, 0x9E, 0xAE, 0x2E, 0xDF,
+ 0xE6, 0xF2, 0x3F, 0xC6, 0xD5, 0xAA, 0xFC, 0x23,
+ 0xAB, 0xCB, 0x96, 0x49, 0xC4, 0xEB, 0xAF, 0x18,
+ 0x14, 0x27, 0xFB, 0xE7, 0x1C, 0x34, 0xF7, 0x22,
+ 0x69, 0xA3, 0xD2, 0xFD, 0x9E, 0x9F, 0x29, 0xA9,
+ 0x50, 0x34, 0x3C, 0x4F, 0xDD, 0xE5, 0xAB, 0xE6,
+ 0xAC, 0x99, 0x80, 0x50, 0x7A, 0x4F, 0x79, 0xD2,
+ 0xC2, 0xC6, 0x31, 0x8F, 0xF6, 0xD6, 0xAA, 0x57,
+ 0x00, 0xA2, 0x4B, 0x61, 0xBA, 0xD6, 0x28, 0xD3,
+ 0xFA, 0x93, 0xE4, 0x65, 0x53, 0x81, 0xD3, 0x01,
+ 0xF1, 0xDA, 0x7A, 0x12, 0x85, 0x17, 0x5A, 0x7E,
+ 0x35, 0x21, 0x6C, 0xF0, 0x18, 0x34, 0xA4, 0xF4,
+ 0xDD, 0x24, 0xEB, 0x86, 0xDC, 0xD0, 0xF7, 0xAB,
+ 0x41, 0xB5, 0x59, 0x3F, 0x22, 0x7B, 0xCF, 0xDB,
+ 0x61, 0x4D, 0x61, 0x58, 0x55, 0xA5, 0x23, 0xCE,
+ 0x69, 0x2D, 0x5C, 0x24, 0x73, 0xA2, 0x80, 0x3F,
+ 0x67, 0xB7, 0x66, 0xD8, 0x30, 0x87, 0xFE, 0x74,
+ 0x23, 0x35, 0xFD, 0xD8, 0xA7, 0xD4, 0xAC, 0x02,
+ 0x40, 0xF6, 0xCA, 0x9B, 0xB3, 0xB4, 0x73, 0xEA,
+ 0x67, 0x39, 0xB4, 0x1B, 0xB4, 0x45, 0xFB, 0xB2,
+ 0xF9, 0xDB, 0x8E, 0x90, 0x29, 0x62, 0x9D, 0x9D,
+ 0x73, 0x30, 0x6C, 0x51, 0x56, 0xA6, 0x9B, 0x9A,
+ 0xE9, 0x33, 0xCA, 0xC8, 0xED, 0xE4, 0x58, 0x91,
+ 0x82, 0x17, 0x10, 0x0F, 0x2D, 0xF7, 0x82, 0xCD,
+ 0x25, 0x61, 0x45, 0xCD, 0xDD, 0x66, 0xF1, 0x8A,
+ 0xDC, 0x08, 0xF8, 0x53, 0xF6, 0x07, 0x8E, 0x3A,
+ 0x6F, 0x0B, 0xF0, 0x9D, 0x8F, 0xFE, 0xDD, 0xCF,
+ 0x94, 0xDD, 0xB2, 0x1F, 0x1A, 0xFF, 0x08, 0x22,
+ 0x3D, 0xEE, 0x45, 0x6B, 0xD2, 0x5A, 0xF3, 0x15,
+ 0x93,
+
+ 0xCC, 0x0E, 0xCA, 0xDF, 0xEF, 0xC6, 0xC6, 0x35,
+ 0x66, 0x95, 0xFF, 0xCE, 0x3F, 0x13, 0x97, 0xEA,
+ 0xEC, 0xB9, 0xEB, 0x1F, 0x82, 0x4E, 0x6A, 0xFF,
+ 0xB0, 0x0A, 0x75, 0xAB, 0xBC, 0x6B, 0xF1, 0xC4,
+ 0xEE, 0xB8, 0x8C, 0xAE, 0x52, 0xED, 0x7C, 0x9E,
+ 0xF3, 0xE2, 0x74, 0xAD, 0x95, 0x65, 0x8F, 0x2D,
+ 0x1A, 0x93, 0xF5, 0x35, 0x5D, 0x5E, 0x7F, 0x5A,
+ 0x22, 0x9F, 0x48, 0x81, 0x25, 0xDE, 0xB1, 0xC3,
+ 0x0A, 0xD6, 0x7E, 0x9E, 0x77, 0xF0, 0x1F, 0x77,
+ 0xE0, 0x85, 0xBB, 0xFA, 0xC5, 0x87, 0xC7, 0x17,
+ 0x0A, 0x7B, 0x3D, 0x85, 0xD4, 0xA9, 0xCA, 0x98,
+ 0xCC, 0x08, 0xD5, 0x40, 0x58, 0x6A, 0x0D, 0xFE,
+ 0xBC, 0x4D, 0xBE, 0x46, 0x9E, 0xC0, 0x84, 0xF4,
+ 0x63, 0xE7, 0xEA, 0xFD, 0x7B, 0x73, 0x1D, 0xDB,
+ 0xE2, 0xD7, 0x51, 0x6D, 0xB2, 0x4F, 0x79, 0x37,
+ 0x9E, 0x37, 0x39, 0xE9, 0xD7, 0xCB, 0x7F, 0x56,
+ 0x5E, 0x68, 0xCC, 0x73, 0x7B, 0xBA, 0x3D, 0x76,
+ 0x0A, 0x41, 0x0B, 0x83, 0xC5, 0xAA, 0xCF, 0x7E,
+ 0xDA, 0x40, 0xB6, 0xCB, 0xC1, 0x76, 0xE5, 0x21,
+ 0xC3, 0xC8, 0xDB, 0x01, 0x2A, 0x87, 0xFF, 0x9E,
+ 0xC7, 0x58, 0xD5, 0xC8, 0x22, 0x37, 0x3F, 0x1F,
+ 0x49, 0xF0, 0x9F, 0x7C, 0x60, 0x91, 0x8C, 0xC5,
+ 0x51, 0xE3, 0x5F, 0x7A, 0x98, 0x0B, 0x3E, 0xE1,
+ 0xAA, 0xC8, 0xE4, 0x3C, 0xC5, 0x98, 0xC0, 0xE5,
+ 0x00, 0x5C, 0xEB, 0x57, 0xAF, 0xF2, 0x67, 0x30,
+ 0x11, 0xB0, 0xD8, 0x82, 0x8A, 0x5A, 0x97, 0xC8,
+ 0xFC, 0x09, 0xD7, 0x74, 0x98, 0xC9, 0x8D, 0xB5,
+ 0x1A, 0x96, 0x79, 0x47, 0xDE, 0x9B, 0x7C, 0xF3,
+ 0x86, 0x80, 0x87, 0x2C, 0x2F, 0xC6, 0xA6, 0x17,
+ 0x85, 0xF3, 0xD1, 0xEE, 0x33, 0x68, 0x7A, 0xCC,
+ 0x54, 0x4A, 0x08, 0x18, 0x8F, 0x20, 0x08, 0x33,
+ 0x43, 0x25, 0x05, 0x9B, 0x21, 0xB2, 0x49, 0xA5,
+ 0x33, 0xC0,
+
+ 0x62, 0xD2, 0x23, 0x2D, 0x6D, 0xC4, 0x02, 0x15,
+ 0x9C, 0xC7, 0x37, 0x08, 0xEA, 0x73, 0x56, 0xB4,
+ 0x77, 0xEE, 0x14, 0xEC, 0x2B, 0x86, 0x51, 0xA0,
+ 0x63, 0x54, 0x00, 0xD4, 0xDE, 0x91, 0xE9, 0x94,
+ 0x3F, 0x32, 0xE6, 0x44, 0x49, 0xF7, 0xBD, 0x4C,
+ 0xFA, 0x07, 0xFB, 0xCB, 0x86, 0xFC, 0xBA, 0x1B,
+ 0x66, 0x52, 0xE3, 0x2C, 0x52, 0x5C, 0x07, 0xD7,
+ 0xFF, 0x08, 0x93, 0x73, 0x30, 0x4E, 0xB8, 0x97,
+ 0x8E, 0xB5, 0xEB, 0x24, 0xF7, 0x26, 0xB5, 0x21,
+ 0xEA, 0x1A, 0x62, 0x1B, 0xAC, 0x12, 0x83, 0xB1,
+ 0xB2, 0xAB, 0x1C, 0x1C, 0x69, 0x7D, 0x5C, 0x9D,
+ 0x4E, 0x20, 0x13, 0x52, 0x6B, 0x88, 0xB6, 0xBE,
+ 0x0E, 0x8D, 0x23, 0xD4, 0x14, 0xF5, 0x99, 0xEB,
+ 0x2E, 0xC8, 0x4D, 0x38, 0x57, 0x47, 0x70, 0x18,
+ 0x65, 0xB5, 0xB8, 0xB4, 0x29, 0x99, 0xA2, 0x4B,
+ 0xAA, 0x5A, 0xEC, 0x8B, 0xCA, 0x9F, 0xE9, 0x6D,
+ 0x8B, 0x0D, 0xEC, 0x0A, 0xCB, 0xD8, 0xF7, 0x0C,
+ 0x7B, 0x22, 0xB0, 0xE8, 0x3C, 0x4F, 0x0C, 0xEC,
+ 0x7E, 0x2D, 0x8F, 0x93, 0x2C, 0xC0, 0xA8, 0x40,
+ 0x48, 0xAA, 0xAF, 0x83, 0x08, 0xBF, 0xBF, 0x5C,
+ 0xBE, 0xB8, 0xAD, 0xC0, 0xCC, 0xDC, 0x7D, 0x00,
+ 0x2B, 0x2B, 0xC7, 0x74, 0xB0, 0x77, 0x95, 0x5F,
+ 0xE9, 0xA1, 0x65, 0x45, 0xB0, 0xBB, 0xEF, 0xD8,
+ 0xFA, 0x1D, 0x1F, 0x66, 0xEF, 0x3B, 0x68, 0x7B,
+ 0x67, 0x9F, 0xFF, 0xA4, 0xB5, 0x24, 0x69, 0xAB,
+ 0x84, 0xE3, 0x75, 0x69, 0x56, 0x72, 0x19, 0x0D,
+ 0x47, 0xA3, 0xF8, 0xAE, 0xA1, 0x4E, 0xB0, 0x4C,
+ 0xAA, 0x0F, 0xF9, 0x08, 0xEA, 0x8F, 0x69, 0xFC,
+ 0x60, 0xF4, 0x91, 0xFF, 0x08, 0xD5, 0xD4, 0xB4,
+ 0xD2, 0x4B, 0xBD, 0x4E, 0x3F, 0x53, 0x34, 0x06,
+ 0x4A, 0x26, 0x57, 0x0F, 0xF2, 0xDE, 0x9D, 0x02,
+ 0xA4, 0xE0, 0x0D, 0xD7, 0x2C, 0x5F, 0x5F, 0x05,
+ 0x4F, 0x60, 0x38,
+
+ 0x0D, 0xEC, 0xE4, 0x86, 0xF5, 0x6D, 0xC1, 0x52,
+ 0x88, 0x55, 0xB9, 0x1D, 0x2D, 0xD7, 0x0A, 0xB4,
+ 0x5C, 0xB2, 0xDE, 0xF6, 0xBD, 0x91, 0x5D, 0x8D,
+ 0x0D, 0xB0, 0xD8, 0x54, 0x56, 0x62, 0xF1, 0x94,
+ 0xB5, 0xEE, 0x73, 0x23, 0xF2, 0x25, 0xF5, 0x7E,
+ 0x6A, 0xBF, 0x8A, 0xAA, 0x1C, 0x66, 0xCB, 0xA0,
+ 0xD6, 0xB2, 0xFC, 0x94, 0x6E, 0x26, 0x49, 0xF8,
+ 0xDE, 0xC0, 0xD8, 0x04, 0x93, 0x80, 0x16, 0x52,
+ 0xA6, 0xDE, 0x3F, 0x87, 0x4E, 0x2F, 0x93, 0xBD,
+ 0xAA, 0x8D, 0xA8, 0x86, 0x27, 0xAC, 0x6D, 0xA0,
+ 0x13, 0x81, 0xF6, 0xE7, 0x7D, 0xBC, 0xF1, 0x09,
+ 0x38, 0x09, 0x93, 0xC5, 0x94, 0x84, 0x0F, 0x4E,
+ 0x28, 0xCA, 0x29, 0x4D, 0xED, 0xDC, 0x91, 0xDC,
+ 0xEC, 0x16, 0xF7, 0x86, 0x4C, 0x0B, 0x2C, 0xDA,
+ 0xCE, 0x2B, 0x1B, 0xB4, 0xFC, 0x6F, 0xA5, 0x7C,
+ 0xE2, 0xC0, 0xAD, 0xC7, 0xA7, 0xE1, 0x28, 0x03,
+ 0xD5, 0xB3, 0x30, 0x51, 0xA2, 0x24, 0x2F, 0x9E,
+ 0x16, 0x48, 0x54, 0x6B, 0x36, 0x60, 0x22, 0x58,
+ 0x00, 0xFF, 0x40, 0x59, 0x17, 0x36, 0x1C, 0x2C,
+ 0x58, 0x0F, 0xC0, 0x5D, 0x41, 0x47, 0x7F, 0xE3,
+ 0xB1, 0x5F, 0x0A, 0x88, 0xBC, 0xBA, 0x83, 0xBF,
+ 0x3D, 0x0B, 0xDF, 0xFC, 0xD3, 0x55, 0xDF, 0x72,
+ 0x0D, 0x8A, 0xAF, 0x4D, 0xF4, 0x0C, 0x0F, 0x8C,
+ 0xE9, 0xEE, 0xA5, 0xA7, 0xFF, 0x87, 0x81, 0x2E,
+ 0x38, 0x04, 0x76, 0xAE, 0xA2, 0xE6, 0x84, 0x73,
+ 0xFF, 0xEC, 0xEE, 0xA3, 0x40, 0xA8, 0x67, 0x8C,
+ 0xD6, 0x68, 0x70, 0xA0, 0x6B, 0x3F, 0x0D, 0x45,
+ 0xE0, 0xA0, 0x29, 0x38, 0xF8, 0xD5, 0x58, 0x59,
+ 0xBD, 0x9B, 0x2B, 0xD3, 0x8B, 0x45, 0x3D, 0xDB,
+ 0x79, 0x0F, 0x25, 0xE7, 0xF9, 0xC7, 0x30, 0xC8,
+ 0x92, 0xC1, 0x99, 0xBE, 0xEC, 0xAF, 0x68, 0xDF,
+ 0x9F, 0xEC, 0x4C, 0x8C, 0xD8, 0x7A, 0xEF, 0x07,
+ 0x6E, 0x14, 0xF4, 0x41,
+
+ 0x93, 0x45, 0x33, 0x61, 0xF0, 0xF2, 0x27, 0x76,
+ 0x4C, 0x53, 0x60, 0xAE, 0x83, 0xB0, 0x90, 0x70,
+ 0xDB, 0xAE, 0x2F, 0x1A, 0xCF, 0xF2, 0xC6, 0x50,
+ 0x36, 0x1B, 0x2E, 0x75, 0xF2, 0x4F, 0x1B, 0x9B,
+ 0x81, 0x2F, 0x49, 0x96, 0xED, 0x05, 0x69, 0x07,
+ 0x0C, 0x6B, 0x5A, 0x35, 0x11, 0x6B, 0x29, 0xC6,
+ 0x07, 0xF5, 0x68, 0xAF, 0x26, 0xE1, 0xEB, 0x71,
+ 0x53, 0x4A, 0xC0, 0x5A, 0x1B, 0xDD, 0x49, 0x28,
+ 0x90, 0xE3, 0xDB, 0x1F, 0x86, 0xB1, 0xAB, 0x4A,
+ 0x64, 0x39, 0x8F, 0x83, 0xA7, 0x37, 0x1B, 0xC9,
+ 0xB6, 0xEA, 0x5E, 0xA8, 0x25, 0x87, 0x78, 0x52,
+ 0xA0, 0xE5, 0xA3, 0x26, 0x74, 0x66, 0xCC, 0x0A,
+ 0x92, 0x7D, 0x9B, 0x4B, 0xAD, 0x79, 0x7F, 0x87,
+ 0x9E, 0x0A, 0xF9, 0xDE, 0xB0, 0x31, 0x2B, 0xDC,
+ 0xC8, 0x29, 0xD0, 0xAC, 0x3C, 0xD8, 0x60, 0x19,
+ 0xA5, 0xF6, 0x50, 0xC1, 0xBA, 0x0F, 0xE4, 0x4A,
+ 0x07, 0xE8, 0xA5, 0xB7, 0x6C, 0x88, 0xF1, 0xBE,
+ 0xAF, 0x2F, 0x40, 0x9B, 0xB3, 0x98, 0x28, 0x43,
+ 0x25, 0xBB, 0x23, 0x1C, 0xF3, 0x98, 0x19, 0x9E,
+ 0x9E, 0x3D, 0xC0, 0xFF, 0x05, 0xA8, 0x35, 0xCD,
+ 0x47, 0xB7, 0xB3, 0xEF, 0xC9, 0x38, 0x36, 0xE7,
+ 0xF9, 0x6F, 0x5B, 0x6E, 0x79, 0xCB, 0x08, 0x49,
+ 0x6F, 0x4C, 0x17, 0xC2, 0x91, 0x7E, 0x8B, 0x86,
+ 0x57, 0x30, 0x8F, 0x92, 0x94, 0x34, 0x10, 0x1B,
+ 0xE5, 0x8F, 0xCC, 0xAF, 0xD0, 0x87, 0xDA, 0x9A,
+ 0xF2, 0x09, 0x99, 0x6C, 0x8E, 0x50, 0x91, 0x7D,
+ 0x7C, 0x4D, 0x3E, 0x24, 0xFF, 0xD4, 0xC1, 0xAA,
+ 0xA7, 0x80, 0x89, 0xB5, 0x8E, 0x50, 0x7D, 0x49,
+ 0xD4, 0xA0, 0xA1, 0xFD, 0x34, 0xCA, 0xB8, 0xCB,
+ 0x64, 0x76, 0x07, 0x91, 0x39, 0x7D, 0xAE, 0xE2,
+ 0xD9, 0x5A, 0xCB, 0xB7, 0xAD, 0x9E, 0x8C, 0xE8,
+ 0x0A, 0xE8, 0xE9, 0xCC, 0x49, 0x97, 0xC3, 0xE9,
+ 0x96, 0x1A, 0xCE, 0xFF, 0x16,
+
+ 0x3D, 0x76, 0xF1, 0x1D, 0x88, 0x56, 0x8E, 0x23,
+ 0x96, 0xE0, 0x55, 0xE9, 0xF3, 0x36, 0xCE, 0xEA,
+ 0x3C, 0x72, 0x34, 0x12, 0xA4, 0x19, 0x29, 0x74,
+ 0x26, 0xCA, 0xF9, 0xDB, 0xA4, 0x2F, 0x2E, 0xBD,
+ 0xD1, 0x64, 0x97, 0xE2, 0x7E, 0x30, 0x59, 0xDB,
+ 0xBB, 0x7D, 0x42, 0xD2, 0xC1, 0x84, 0x18, 0x1F,
+ 0x67, 0x61, 0x5D, 0x40, 0xE5, 0xD8, 0x83, 0x36,
+ 0x98, 0xAB, 0x2F, 0xE8, 0x24, 0x13, 0xC7, 0x61,
+ 0x0A, 0x71, 0x59, 0x9E, 0x51, 0xE1, 0xBB, 0xCE,
+ 0xEA, 0xE7, 0xFC, 0x7E, 0x92, 0xE0, 0x1F, 0xA5,
+ 0xE3, 0x89, 0x80, 0xBC, 0xA8, 0xCB, 0xDB, 0xFD,
+ 0x49, 0x8D, 0x7F, 0x01, 0x15, 0xA5, 0x35, 0x89,
+ 0x46, 0xB5, 0xBC, 0x8E, 0x96, 0x80, 0x11, 0xCA,
+ 0x6C, 0x56, 0x94, 0x1C, 0x0C, 0xEC, 0x56, 0x78,
+ 0xC9, 0x7E, 0x4A, 0x44, 0xE7, 0xDF, 0x03, 0xA9,
+ 0x32, 0xF5, 0xA2, 0x4C, 0x80, 0xBB, 0x31, 0x9E,
+ 0x00, 0x5D, 0xCD, 0xB2, 0x33, 0x41, 0xCA, 0xA4,
+ 0x8A, 0xB3, 0x52, 0x59, 0xD9, 0x19, 0xD4, 0x98,
+ 0x78, 0xFE, 0xB1, 0x02, 0x6D, 0x52, 0x6F, 0x23,
+ 0xC8, 0xF7, 0xA8, 0xC2, 0xB4, 0x90, 0x69, 0x68,
+ 0x5A, 0xA5, 0xDB, 0x26, 0x93, 0xF0, 0x78, 0x25,
+ 0xC3, 0x94, 0x1F, 0x0A, 0x0B, 0x0F, 0xA8, 0xC2,
+ 0xCB, 0x7B, 0x0D, 0xC9, 0x53, 0x1D, 0x5A, 0xB4,
+ 0x30, 0xF2, 0xDD, 0x15, 0x8D, 0xDE, 0x49, 0x82,
+ 0x94, 0x9B, 0x6E, 0x2D, 0x2D, 0xD7, 0x21, 0x38,
+ 0x98, 0x61, 0xEB, 0xF3, 0xDE, 0xB1, 0xCE, 0x54,
+ 0xB9, 0x7F, 0x9C, 0x4B, 0xF0, 0x8B, 0xD1, 0xBF,
+ 0x6A, 0xA4, 0x57, 0x28, 0x86, 0xE2, 0xB2, 0x74,
+ 0x31, 0x51, 0x9E, 0x30, 0xF5, 0x98, 0x3E, 0x9D,
+ 0x98, 0x21, 0x7C, 0xAD, 0x68, 0x44, 0x91, 0x5C,
+ 0x11, 0x5A, 0x42, 0x0C, 0x84, 0x69, 0x62, 0xD0,
+ 0x98, 0x3D, 0x89, 0x4D, 0xBC, 0x65, 0x38, 0x03,
+ 0x44, 0x76, 0xFF, 0x20, 0x3D, 0x28,
+
+ 0xD4, 0xAE, 0xDA, 0xA8, 0x24, 0x19, 0x06, 0xFB,
+ 0xE9, 0xAD, 0x9F, 0x3C, 0x1D, 0xD6, 0x92, 0x5E,
+ 0x83, 0x58, 0x54, 0xBB, 0xCB, 0x7D, 0x8E, 0x24,
+ 0x0F, 0x0A, 0x43, 0xF5, 0x6D, 0x89, 0x99, 0x4A,
+ 0xB7, 0xDF, 0x8A, 0x84, 0x00, 0x1A, 0xF5, 0x6E,
+ 0x1C, 0xC2, 0xFA, 0x20, 0xE7, 0xC2, 0x41, 0x60,
+ 0x7C, 0xCE, 0x90, 0x8E, 0x16, 0x64, 0x94, 0xDA,
+ 0xE2, 0x3A, 0x8D, 0xDF, 0x21, 0x61, 0x17, 0x3C,
+ 0x72, 0xE3, 0x66, 0x35, 0x0B, 0xF6, 0x30, 0x5C,
+ 0x82, 0x5C, 0x48, 0xA1, 0xE8, 0x21, 0x9C, 0x92,
+ 0xA1, 0x0F, 0xBF, 0x89, 0xC8, 0x7A, 0xEE, 0x18,
+ 0x87, 0x5B, 0x51, 0xF3, 0xF7, 0x0A, 0xA3, 0xB4,
+ 0x2E, 0xDA, 0x4E, 0xAA, 0xAD, 0x6E, 0x70, 0x04,
+ 0xF8, 0x47, 0x1E, 0x5F, 0x43, 0x69, 0x0B, 0x26,
+ 0x4C, 0xBC, 0xDB, 0x46, 0x77, 0x87, 0xA1, 0x9A,
+ 0x04, 0xEF, 0x74, 0x99, 0xEA, 0x29, 0x71, 0x55,
+ 0x9C, 0x2E, 0x47, 0xE3, 0x4A, 0x15, 0xA4, 0xF6,
+ 0xED, 0x5D, 0xBE, 0x4F, 0x94, 0x3F, 0xFD, 0xD3,
+ 0x6E, 0x0E, 0xD9, 0x26, 0x68, 0x9F, 0xC2, 0x8C,
+ 0xA5, 0xA8, 0xF0, 0xFB, 0x53, 0x5F, 0x18, 0xCA,
+ 0xDB, 0xBD, 0x98, 0x96, 0x28, 0xFC, 0xE9, 0x2E,
+ 0x81, 0xE1, 0x0E, 0x3A, 0x77, 0x18, 0x25, 0x9D,
+ 0xB7, 0x67, 0x8C, 0x35, 0x68, 0x4A, 0x88, 0x18,
+ 0x45, 0x6C, 0xE5, 0xCC, 0x22, 0xD2, 0x77, 0x9A,
+ 0x68, 0x0E, 0xC5, 0xA6, 0x1D, 0xAD, 0xDB, 0xB5,
+ 0xFF, 0xEA, 0x7C, 0x7D, 0x19, 0x1B, 0x9D, 0xB9,
+ 0xD0, 0xA7, 0xAB, 0x4D, 0x4A, 0x7D, 0x1A, 0xA5,
+ 0x09, 0x54, 0x84, 0x5C, 0x14, 0x4E, 0xA6, 0x14,
+ 0x6B, 0x22, 0x46, 0x7E, 0x5E, 0xB9, 0x33, 0x97,
+ 0xB5, 0x63, 0x5C, 0xCE, 0xF4, 0xD0, 0xD8, 0x8C,
+ 0xCC, 0xE7, 0x67, 0x01, 0x1B, 0x56, 0x68, 0x54,
+ 0x56, 0x4C, 0x19, 0x1D, 0x05, 0xF8, 0x55, 0xD6,
+ 0x45, 0xC0, 0xAD, 0xD6, 0xEE, 0xD9, 0x03,
+
+ 0x7F, 0x07, 0xFA, 0x8C, 0x77, 0xF1, 0xDA, 0x4E,
+ 0x4B, 0x65, 0x55, 0xA4, 0x12, 0xE8, 0x7F, 0x04,
+ 0x0A, 0xEC, 0x57, 0xFF, 0x30, 0xD1, 0xE2, 0x08,
+ 0x71, 0xEC, 0x5F, 0x72, 0x88, 0x37, 0xC1, 0x33,
+ 0x79, 0xC8, 0x49, 0x47, 0x11, 0xC9, 0x8C, 0xD3,
+ 0x3B, 0x4F, 0x2C, 0x5A, 0xDD, 0x8C, 0x00, 0x8B,
+ 0xF6, 0xC4, 0x07, 0x7E, 0x2C, 0xFA, 0x3A, 0xBF,
+ 0x84, 0xBA, 0x13, 0x31, 0x20, 0x69, 0xAF, 0xBD,
+ 0x61, 0xB0, 0xFF, 0x28, 0x40, 0x1B, 0x5F, 0x1D,
+ 0x87, 0x99, 0x23, 0x95, 0x77, 0x88, 0x3F, 0xBB,
+ 0xFA, 0x55, 0xB5, 0xB2, 0xF7, 0xF3, 0xA6, 0x0B,
+ 0x57, 0x71, 0xF5, 0x7A, 0xE7, 0x23, 0x61, 0x54,
+ 0x13, 0xCB, 0x71, 0x97, 0xDE, 0xFF, 0x0E, 0x23,
+ 0x5C, 0xD4, 0xCC, 0xB1, 0xB8, 0x2F, 0xA1, 0xA5,
+ 0x15, 0xEB, 0xB4, 0x47, 0xA7, 0x7C, 0xEA, 0xD1,
+ 0x23, 0xE7, 0xFE, 0x9D, 0x56, 0xC5, 0x73, 0x9D,
+ 0xE8, 0x90, 0x4E, 0x00, 0xE5, 0x7F, 0x6E, 0x36,
+ 0x6D, 0xEA, 0x8C, 0xBA, 0xC6, 0x9C, 0xA0, 0x27,
+ 0x13, 0x90, 0x35, 0xE7, 0xD5, 0x27, 0x56, 0x50,
+ 0x70, 0x64, 0x03, 0xD2, 0x43, 0xDC, 0x1F, 0x60,
+ 0x4B, 0x5D, 0x48, 0xF1, 0x82, 0xE6, 0x9A, 0xDE,
+ 0xC7, 0xDB, 0x2F, 0x0D, 0xD9, 0xF4, 0xAD, 0xD0,
+ 0xB9, 0xDC, 0x01, 0x09, 0x74, 0x4F, 0x29, 0x71,
+ 0x61, 0x6D, 0xE2, 0xAC, 0xE3, 0x60, 0x9C, 0x4D,
+ 0x9A, 0x26, 0xC9, 0x3D, 0x11, 0x04, 0x83, 0x9F,
+ 0x39, 0x39, 0x0E, 0x44, 0xB2, 0xD3, 0x7A, 0x0D,
+ 0xD7, 0x0B, 0xDB, 0x14, 0x4A, 0x46, 0xA7, 0xB5,
+ 0x34, 0x2C, 0x22, 0x98, 0xBA, 0x6A, 0xBA, 0x4A,
+ 0xDA, 0x30, 0x8C, 0xE7, 0xDF, 0xD8, 0x73, 0x83,
+ 0x8C, 0xB6, 0x7A, 0x73, 0x74, 0xE5, 0x04, 0x32,
+ 0x66, 0x24, 0xC9, 0x45, 0xDA, 0x86, 0xE2, 0xCD,
+ 0xF9, 0xDB, 0x2F, 0x1D, 0xBA, 0x2C, 0xC0, 0x91,
+ 0x06, 0xF7, 0x44, 0xE8, 0x30, 0x34, 0x94, 0x91,
+
+ 0xD5, 0x3B, 0xA6, 0x5A, 0x56, 0xB4, 0xDD, 0xBC,
+ 0xD8, 0xE7, 0x85, 0x2B, 0x3E, 0xFC, 0xBC, 0xD1,
+ 0xB9, 0x68, 0x09, 0xC3, 0xA5, 0xC1, 0x1D, 0x5C,
+ 0x4C, 0x11, 0xAC, 0x4A, 0xA3, 0x96, 0xAB, 0xD2,
+ 0xFD, 0x33, 0xD7, 0x69, 0xD1, 0x95, 0x50, 0xE6,
+ 0x4D, 0x3A, 0xE9, 0x9D, 0x67, 0x68, 0x16, 0x01,
+ 0xE7, 0x8A, 0xE3, 0x90, 0xC8, 0x4D, 0xD4, 0xDF,
+ 0xB0, 0xA1, 0x90, 0x14, 0xC2, 0x32, 0x9A, 0xC2,
+ 0x86, 0xA2, 0x53, 0x72, 0x1A, 0x9A, 0xFE, 0x8E,
+ 0xB1, 0x4C, 0xCD, 0x9F, 0xFF, 0x3F, 0xA6, 0x6A,
+ 0x8E, 0xEB, 0x5E, 0x7C, 0x9D, 0xF3, 0x4B, 0x3B,
+ 0x09, 0xC7, 0x68, 0x71, 0xD5, 0xBA, 0x32, 0x2D,
+ 0xBA, 0x15, 0xE3, 0x63, 0xD7, 0x5A, 0x87, 0x5E,
+ 0x9E, 0xAF, 0xB0, 0x9C, 0xF9, 0x35, 0xA3, 0x67,
+ 0x1B, 0xD5, 0xC7, 0x9C, 0xB5, 0x63, 0x0E, 0x16,
+ 0x9B, 0x2D, 0x25, 0x1E, 0x22, 0x96, 0x0A, 0x96,
+ 0xBE, 0xEF, 0x65, 0xAA, 0xFE, 0x28, 0xB9, 0x55,
+ 0xD0, 0xDC, 0xB2, 0x5C, 0x21, 0x9B, 0x31, 0xF7,
+ 0xDE, 0xD9, 0xA6, 0x86, 0x3D, 0xD8, 0x5F, 0xB4,
+ 0xC5, 0x7A, 0x4D, 0xAB, 0xE5, 0xBC, 0x10, 0xB7,
+ 0x26, 0x15, 0x08, 0x64, 0x58, 0xB0, 0x4F, 0x77,
+ 0xCE, 0xDC, 0xBD, 0x1D, 0xD5, 0x21, 0x9A, 0x9A,
+ 0x93, 0x72, 0x2D, 0x4D, 0x82, 0x36, 0x29, 0xCA,
+ 0xAB, 0x80, 0xD2, 0x02, 0x1D, 0x6C, 0x49, 0x30,
+ 0x56, 0x20, 0x8D, 0xFA, 0xA1, 0x58, 0x3F, 0xA6,
+ 0xCB, 0xF0, 0x41, 0xFB, 0xDD, 0xD0, 0x6D, 0x80,
+ 0x75, 0xE1, 0x36, 0xAC, 0xF8, 0xAE, 0xDB, 0x37,
+ 0xB0, 0xDE, 0x4B, 0x89, 0xFB, 0xC1, 0x1B, 0x23,
+ 0x05, 0xBC, 0x02, 0x87, 0x42, 0x9A, 0x77, 0x23,
+ 0x99, 0xB4, 0x56, 0x7E, 0x7C, 0xD7, 0x61, 0x18,
+ 0xD2, 0x4F, 0x19, 0xE6, 0x05, 0x4D, 0x72, 0xC8,
+ 0xB7, 0xA9, 0x9F, 0xF9, 0x9F, 0xE9, 0x54, 0x34,
+ 0x54, 0x45, 0x7C, 0xA4, 0xCC, 0x3B, 0xFF, 0x2B,
+ 0x58,
+
+ 0xB7, 0x93, 0x32, 0xE4, 0xCA, 0xD7, 0xB5, 0x4F,
+ 0x11, 0xB0, 0x5B, 0x38, 0xB8, 0xC0, 0x90, 0xA8,
+ 0x0E, 0x4B, 0x34, 0x6C, 0xCC, 0x81, 0x82, 0xC5,
+ 0x41, 0x91, 0x0D, 0x1A, 0x47, 0x0E, 0xE6, 0x39,
+ 0x7F, 0xDD, 0xF9, 0xBE, 0xF1, 0xB0, 0xDC, 0x76,
+ 0xB8, 0x2C, 0x2B, 0xAD, 0xA9, 0xE5, 0xCA, 0x70,
+ 0x8D, 0xF1, 0xCA, 0x60, 0x5C, 0x85, 0x2E, 0x73,
+ 0xE7, 0xF8, 0x0A, 0x33, 0xB3, 0x32, 0xC0, 0xCD,
+ 0x64, 0x4C, 0x9C, 0x65, 0x55, 0x2A, 0x60, 0x42,
+ 0xF3, 0xBA, 0xF5, 0xC2, 0x28, 0xFC, 0xFE, 0x32,
+ 0x96, 0xBF, 0x6F, 0x7E, 0x09, 0x82, 0xA5, 0xD0,
+ 0xE4, 0x11, 0x66, 0x67, 0x66, 0xDB, 0x8A, 0x3D,
+ 0x08, 0x40, 0xC4, 0x40, 0x66, 0xF8, 0x1F, 0x86,
+ 0x39, 0xDB, 0xB6, 0x12, 0x11, 0x4E, 0xE4, 0x52,
+ 0xA5, 0x18, 0x4A, 0x3F, 0x04, 0x01, 0x3D, 0x8D,
+ 0x15, 0xEE, 0x28, 0xBD, 0xED, 0x32, 0x11, 0xB8,
+ 0xE9, 0x5E, 0x2A, 0xB7, 0xD3, 0x3C, 0xDD, 0xC6,
+ 0x42, 0xE0, 0x15, 0x20, 0x0B, 0x13, 0x7E, 0x21,
+ 0xFE, 0x7B, 0x5F, 0x46, 0x70, 0xF6, 0x64, 0x73,
+ 0x71, 0x1A, 0x29, 0xD9, 0x07, 0xE0, 0xA9, 0x65,
+ 0x5B, 0x90, 0x17, 0x5E, 0xE6, 0xFC, 0x29, 0xA2,
+ 0x5B, 0xB0, 0x00, 0x54, 0x6C, 0x15, 0xA1, 0x44,
+ 0x66, 0x0F, 0x87, 0xCF, 0x66, 0x04, 0x6F, 0x3F,
+ 0x04, 0xE5, 0xFA, 0x2D, 0x0C, 0x70, 0x43, 0xF0,
+ 0x08, 0x01, 0x62, 0x21, 0x81, 0x65, 0x9F, 0x61,
+ 0xC6, 0x5A, 0x80, 0x64, 0x9D, 0x8E, 0xD7, 0x52,
+ 0xCF, 0xDC, 0x04, 0x50, 0x0A, 0x98, 0x5A, 0xF2,
+ 0x9F, 0x6A, 0xAF, 0xDA, 0x96, 0x35, 0x34, 0xF9,
+ 0xAB, 0x1E, 0x17, 0xC3, 0x18, 0x90, 0xFB, 0x07,
+ 0x5E, 0xA0, 0x02, 0x4C, 0x0C, 0xE1, 0xE9, 0x06,
+ 0x7F, 0x1F, 0xC1, 0xA2, 0x77, 0x63, 0xF0, 0x96,
+ 0xEE, 0x87, 0xC8, 0x28, 0x79, 0x17, 0x33, 0x2D,
+ 0x16, 0x43, 0x9A, 0x79, 0x32, 0xA9, 0x3D, 0x1F,
+ 0x35, 0x3D,
+
+ 0xD1, 0x6C, 0xFF, 0x29, 0x4F, 0xC3, 0x29, 0xC5,
+ 0xC9, 0x5B, 0xDC, 0x81, 0xD1, 0xB3, 0x55, 0xA8,
+ 0x5E, 0xE2, 0xC9, 0xE3, 0xFC, 0x16, 0x30, 0x02,
+ 0xAB, 0x43, 0x26, 0x7E, 0xD1, 0xCD, 0x2B, 0x06,
+ 0xE8, 0x4E, 0xDA, 0xA3, 0xD3, 0xD3, 0x87, 0x05,
+ 0xB3, 0x05, 0x8C, 0xCF, 0xAE, 0xEF, 0x15, 0x33,
+ 0xCE, 0x72, 0x64, 0x52, 0x88, 0x78, 0x20, 0x1B,
+ 0xF1, 0x7E, 0xC9, 0x46, 0x13, 0xCF, 0xD9, 0xF2,
+ 0x4B, 0x1C, 0xA6, 0x96, 0xAF, 0x02, 0xAD, 0x6F,
+ 0xDB, 0xAD, 0x6F, 0x04, 0x55, 0xA2, 0x2C, 0x9C,
+ 0x56, 0xB6, 0x07, 0x8A, 0x87, 0x3F, 0xD6, 0x06,
+ 0x90, 0x4C, 0x6D, 0x5E, 0xE5, 0x16, 0x21, 0x46,
+ 0x00, 0x88, 0x77, 0x58, 0x0E, 0x9E, 0x89, 0xFE,
+ 0x3F, 0x20, 0x6A, 0x17, 0x64, 0x9C, 0x63, 0x71,
+ 0x3C, 0xDB, 0x36, 0xE3, 0x8A, 0xA6, 0x7A, 0xD5,
+ 0x1A, 0x27, 0x75, 0x4C, 0xD9, 0xF3, 0xF0, 0x02,
+ 0x2B, 0x3D, 0xE5, 0xF1, 0xDE, 0x98, 0x98, 0x62,
+ 0x18, 0x17, 0xAE, 0xD2, 0x80, 0xA7, 0xA3, 0x82,
+ 0xBF, 0x30, 0xC8, 0xC9, 0x68, 0x6A, 0x2F, 0x40,
+ 0x8A, 0x2F, 0x8A, 0x39, 0xB4, 0x60, 0x6F, 0xE1,
+ 0x0F, 0x19, 0xB1, 0x4C, 0x82, 0x9A, 0x11, 0xB4,
+ 0x98, 0x74, 0xE7, 0xAF, 0xD4, 0x21, 0x5E, 0xD8,
+ 0x30, 0xA1, 0x53, 0xF3, 0xD2, 0xDE, 0x02, 0x9F,
+ 0xA6, 0xA8, 0x4D, 0x03, 0x2A, 0x45, 0xE3, 0x49,
+ 0x98, 0xE2, 0xF7, 0x71, 0x9F, 0xBC, 0x93, 0xDE,
+ 0xF6, 0x7E, 0x12, 0xC1, 0x37, 0xB0, 0x93, 0x4E,
+ 0x89, 0x16, 0x39, 0x2B, 0xF6, 0x28, 0x30, 0x75,
+ 0xC0, 0x43, 0xA9, 0x3D, 0x1F, 0xD3, 0xFD, 0x56,
+ 0xF7, 0x65, 0xFC, 0x08, 0x3C, 0x9B, 0x1C, 0x33,
+ 0x57, 0x0B, 0xAB, 0x4B, 0xFE, 0xD4, 0x50, 0xFC,
+ 0x9D, 0x42, 0xF7, 0x8D, 0xB4, 0x50, 0xF5, 0xA9,
+ 0x54, 0x00, 0x74, 0x93, 0x59, 0x6B, 0x6F, 0x95,
+ 0x31, 0xEE, 0xF5, 0xC4, 0x4A, 0x9C, 0x33, 0x27,
+ 0x6E, 0x1D, 0x4A,
+
+ 0xB5, 0xEE, 0x2C, 0xC7, 0x88, 0xD2, 0x63, 0x3E,
+ 0xF6, 0x8E, 0xC1, 0xA3, 0xD2, 0x39, 0x8E, 0xF6,
+ 0xD3, 0x44, 0x7C, 0xA6, 0x27, 0x6E, 0x67, 0x66,
+ 0x0F, 0x68, 0xF9, 0xE2, 0xE4, 0xA2, 0x9B, 0x59,
+ 0x6D, 0x26, 0xE2, 0x4B, 0xF1, 0x82, 0x5C, 0x67,
+ 0xE9, 0x55, 0xEE, 0xB6, 0xA0, 0xE3, 0x32, 0xEE,
+ 0x2A, 0x33, 0x2F, 0x6A, 0x2B, 0xBC, 0xE8, 0xB9,
+ 0x45, 0xCD, 0x0F, 0xF0, 0x84, 0xB6, 0x5D, 0xC5,
+ 0xAC, 0xD7, 0x45, 0x4B, 0x5A, 0xE4, 0xD5, 0x07,
+ 0x6D, 0x30, 0x0A, 0x9E, 0x73, 0x0E, 0x7D, 0x5F,
+ 0x8A, 0x2C, 0x7A, 0xE4, 0xD0, 0x1B, 0xE7, 0x02,
+ 0x93, 0x2E, 0xCE, 0x3C, 0xA1, 0xB1, 0x48, 0x5A,
+ 0xD6, 0xC0, 0x38, 0x0F, 0x13, 0xC7, 0x8B, 0x0F,
+ 0x4D, 0x90, 0xFC, 0x22, 0xC5, 0x74, 0xC6, 0xE0,
+ 0xFE, 0x1B, 0x2D, 0xEA, 0x3E, 0xDB, 0xC1, 0xCA,
+ 0x7F, 0x0D, 0xA0, 0xBB, 0x62, 0x0B, 0x51, 0x46,
+ 0xD4, 0xAB, 0x21, 0xE9, 0x6A, 0x13, 0x55, 0xEC,
+ 0x00, 0x16, 0xF5, 0xA3, 0xE8, 0x59, 0x90, 0xFB,
+ 0x56, 0xA5, 0x4B, 0x7F, 0x3F, 0xAA, 0x2E, 0x27,
+ 0x6F, 0xEC, 0x7B, 0xD1, 0xFA, 0x79, 0x36, 0x95,
+ 0x17, 0x84, 0xE0, 0xF1, 0xFB, 0xCA, 0xE2, 0x71,
+ 0x18, 0xAF, 0x49, 0x4D, 0x02, 0x51, 0xAB, 0x0C,
+ 0x56, 0x0A, 0xAF, 0x96, 0x0A, 0xD3, 0x57, 0x93,
+ 0xA1, 0x8E, 0xD1, 0x32, 0xD4, 0x1D, 0x62, 0xE1,
+ 0x1F, 0x4D, 0x00, 0xD4, 0x0B, 0x6F, 0xAE, 0x69,
+ 0x67, 0xAA, 0x2D, 0x75, 0x17, 0x0E, 0xE8, 0x72,
+ 0x91, 0x11, 0x05, 0xBB, 0x94, 0xBE, 0x0B, 0x2C,
+ 0x05, 0xF3, 0x09, 0x98, 0xAA, 0xA3, 0x77, 0xB9,
+ 0xAF, 0x75, 0x29, 0x57, 0xA0, 0x7F, 0x70, 0x53,
+ 0x4E, 0xEB, 0xD5, 0x15, 0x50, 0x60, 0x1D, 0x7B,
+ 0x3F, 0x3F, 0x65, 0x4E, 0xE0, 0x4A, 0x47, 0xEF,
+ 0xBA, 0x68, 0x01, 0xEB, 0xA5, 0x09, 0x4C, 0xE4,
+ 0xF6, 0xAA, 0xE0, 0x00, 0x43, 0x5B, 0x2E, 0x09,
+ 0xFE, 0xD0, 0x4E, 0xE8,
+
+ 0x06, 0x49, 0x5B, 0x9A, 0xCF, 0x47, 0x2B, 0x04,
+ 0xBE, 0x1B, 0x98, 0x6A, 0xB5, 0x21, 0x6D, 0x0E,
+ 0x18, 0x9B, 0x87, 0xA4, 0x97, 0x13, 0xF5, 0x7E,
+ 0x94, 0x92, 0xB3, 0x69, 0xA1, 0xD5, 0x25, 0x46,
+ 0x26, 0x8E, 0x6B, 0x47, 0x0A, 0x77, 0x48, 0x51,
+ 0xB9, 0xAF, 0x64, 0x37, 0x70, 0x64, 0xBD, 0x98,
+ 0x16, 0x1A, 0x46, 0xAA, 0xFA, 0x0C, 0xB2, 0x3C,
+ 0x6F, 0x23, 0xA5, 0x6C, 0x81, 0x0B, 0x49, 0x7C,
+ 0x75, 0xE6, 0x0B, 0x47, 0x49, 0xDB, 0x70, 0xC5,
+ 0x26, 0x75, 0x20, 0x3E, 0xE2, 0x28, 0xD9, 0x1A,
+ 0xE2, 0x96, 0x9D, 0xAE, 0x29, 0x53, 0x9A, 0xE2,
+ 0xFE, 0xC9, 0xF5, 0x3B, 0x02, 0x40, 0x13, 0xF1,
+ 0x10, 0x27, 0x1A, 0x67, 0x97, 0x9C, 0xF6, 0xC5,
+ 0xBA, 0xE6, 0x3D, 0xA4, 0xA8, 0x67, 0xCF, 0xB6,
+ 0x35, 0xC7, 0x6B, 0xC6, 0x9C, 0x85, 0x25, 0x14,
+ 0x20, 0xC6, 0x48, 0x23, 0x26, 0x29, 0xE9, 0xBE,
+ 0x79, 0x89, 0xFA, 0x26, 0x2E, 0xB9, 0xC3, 0x54,
+ 0x28, 0x8B, 0xE2, 0xEF, 0xBC, 0xB2, 0x19, 0xC3,
+ 0x40, 0x85, 0x8A, 0x59, 0x06, 0x96, 0xDF, 0x39,
+ 0x03, 0x6E, 0xA0, 0xF8, 0x20, 0xD9, 0x3B, 0x72,
+ 0x80, 0xCC, 0x15, 0xBF, 0xB6, 0x2B, 0x15, 0x8A,
+ 0xC2, 0x71, 0x60, 0xEE, 0x51, 0x80, 0xCB, 0x61,
+ 0x7A, 0xDB, 0x17, 0x18, 0x80, 0xE5, 0x2F, 0xB9,
+ 0xB9, 0x36, 0xE3, 0xED, 0x7B, 0x7C, 0x23, 0xF7,
+ 0xBB, 0xBE, 0x61, 0xF1, 0xAF, 0x38, 0x5E, 0xAC,
+ 0x6E, 0x8F, 0x5A, 0x46, 0xB9, 0xD6, 0x4D, 0x51,
+ 0x5A, 0x7F, 0x3C, 0x34, 0xE5, 0x5E, 0x28, 0xB4,
+ 0x00, 0xD5, 0x76, 0xF6, 0x04, 0x94, 0x00, 0x36,
+ 0x23, 0xD1, 0x87, 0xA7, 0x0D, 0x55, 0xF4, 0x8A,
+ 0x89, 0x3A, 0x32, 0x9D, 0x08, 0xEB, 0xB6, 0x6F,
+ 0xED, 0xF0, 0xF8, 0x8F, 0x25, 0x3B, 0xAC, 0x6E,
+ 0xF5, 0x2B, 0x37, 0x4E, 0x4C, 0x28, 0x19, 0x69,
+ 0x66, 0x04, 0x40, 0x09, 0xE4, 0x1F, 0x82, 0x6F,
+ 0x5E, 0x40, 0x4C, 0x16, 0x4B,
+
+ 0xBF, 0x12, 0xC4, 0xD2, 0xDD, 0xF1, 0x90, 0x50,
+ 0x38, 0x11, 0x8E, 0x5D, 0x20, 0x49, 0x64, 0xEB,
+ 0x08, 0xE0, 0x5F, 0xFF, 0x81, 0xC1, 0x23, 0x7F,
+ 0xA0, 0xBB, 0xB4, 0x28, 0x61, 0xA2, 0x99, 0xEB,
+ 0x44, 0x5A, 0x26, 0xF3, 0xF1, 0x76, 0x41, 0xF7,
+ 0x92, 0xFD, 0x6A, 0xB1, 0x72, 0x92, 0xBF, 0x62,
+ 0x92, 0x57, 0x46, 0x45, 0x0B, 0x5E, 0xA3, 0x33,
+ 0x64, 0x79, 0xE9, 0x3B, 0x50, 0x54, 0x62, 0xC1,
+ 0xB8, 0x5E, 0x45, 0x5A, 0x5F, 0xB4, 0xBB, 0x5F,
+ 0x6A, 0x01, 0x8D, 0x1B, 0x79, 0x76, 0x34, 0x08,
+ 0xF9, 0x42, 0xE4, 0xD6, 0x42, 0xDD, 0x16, 0x80,
+ 0xD4, 0x7D, 0x7D, 0xC4, 0x09, 0xAC, 0x96, 0xF8,
+ 0xB5, 0x8A, 0xF7, 0xBF, 0x92, 0xDB, 0x5D, 0xB7,
+ 0x15, 0x91, 0x6F, 0x96, 0xB5, 0x4C, 0x3E, 0x27,
+ 0xD8, 0xE2, 0xE1, 0x6F, 0x9D, 0x9B, 0xBB, 0x99,
+ 0x5D, 0xB5, 0x33, 0x55, 0xB3, 0x12, 0xFF, 0x64,
+ 0xBF, 0xB7, 0x58, 0xA0, 0x40, 0x9B, 0x6E, 0x35,
+ 0x26, 0x88, 0x13, 0x0B, 0x82, 0xA7, 0x2F, 0x10,
+ 0x70, 0x2B, 0xAF, 0x24, 0x1F, 0xAA, 0x62, 0xD2,
+ 0xBA, 0x0F, 0x3A, 0x29, 0x88, 0x48, 0xCB, 0xC9,
+ 0x60, 0x20, 0x73, 0x07, 0x46, 0x4D, 0x62, 0x2B,
+ 0x52, 0x2D, 0x39, 0xCB, 0x79, 0x63, 0x29, 0x54,
+ 0xA7, 0x4E, 0x3A, 0xD7, 0xD4, 0x51, 0x2D, 0xDD,
+ 0xBF, 0x6C, 0x16, 0x4E, 0xA7, 0x49, 0xEA, 0xE2,
+ 0x78, 0xBA, 0x84, 0x89, 0x7D, 0x5F, 0xA8, 0xFD,
+ 0x89, 0x2F, 0xA0, 0xE0, 0x1E, 0xE5, 0x51, 0x8D,
+ 0xE9, 0xE1, 0x73, 0x79, 0xE5, 0x28, 0x62, 0xFB,
+ 0x15, 0xD3, 0x44, 0xAF, 0xED, 0xCE, 0x1F, 0xB6,
+ 0x2D, 0x26, 0x5D, 0xDA, 0xED, 0x01, 0x30, 0x4D,
+ 0x72, 0x4F, 0x23, 0xF0, 0x5A, 0x1E, 0xC9, 0xAF,
+ 0xCF, 0x75, 0xA3, 0x15, 0xAE, 0x29, 0xF6, 0xD7,
+ 0xE4, 0xA9, 0x95, 0xF4, 0x39, 0x3E, 0xF6, 0x99,
+ 0xB5, 0xB3, 0x60, 0xDE, 0x7C, 0x26, 0xDD, 0xF0,
+ 0xD3, 0x04, 0x0A, 0xFC, 0xE9, 0xAE,
+
+ 0xB0, 0x1B, 0x1C, 0xC2, 0xC4, 0x72, 0x71, 0xBF,
+ 0x61, 0x44, 0xD2, 0x9C, 0x4B, 0x14, 0x90, 0x14,
+ 0xC5, 0x89, 0x3D, 0xC7, 0x32, 0x07, 0xA7, 0xF5,
+ 0x64, 0xC1, 0xDD, 0x7D, 0x42, 0x2C, 0x3D, 0xDE,
+ 0x61, 0xDD, 0x78, 0x94, 0xB6, 0xB5, 0xF8, 0x47,
+ 0xEE, 0x5C, 0x2A, 0xA3, 0x32, 0xB5, 0x63, 0x3E,
+ 0x8C, 0xE6, 0x2F, 0x56, 0x1A, 0x24, 0xAA, 0xBD,
+ 0xA6, 0xAF, 0x30, 0x90, 0x7D, 0xF2, 0x73, 0x86,
+ 0x4D, 0x93, 0x74, 0xF1, 0xD8, 0x9B, 0x70, 0xDC,
+ 0xA5, 0xCC, 0xA8, 0xF9, 0x27, 0xBA, 0xA0, 0x3D,
+ 0x4D, 0x11, 0x19, 0xA5, 0x23, 0xE0, 0xC1, 0xC2,
+ 0xF7, 0x18, 0xDA, 0xCA, 0x23, 0x7E, 0x91, 0x56,
+ 0x72, 0xF7, 0xCE, 0xB4, 0xBF, 0x31, 0x2A, 0x61,
+ 0x9B, 0x7D, 0x82, 0xDF, 0xF2, 0xC7, 0x04, 0x74,
+ 0xD4, 0x2F, 0x14, 0x02, 0x4C, 0xC9, 0x12, 0x6D,
+ 0xF9, 0x67, 0x9C, 0xC5, 0x97, 0x3B, 0x9C, 0x54,
+ 0xA4, 0x45, 0xDA, 0xA5, 0xE8, 0xDB, 0xF7, 0x95,
+ 0x62, 0x0E, 0xE3, 0x25, 0x95, 0xC6, 0x68, 0xA1,
+ 0xBD, 0xC7, 0x78, 0xBD, 0x7E, 0xF8, 0x98, 0xDE,
+ 0xDA, 0x30, 0x75, 0xB6, 0xD0, 0xE1, 0x67, 0x42,
+ 0x6D, 0xE0, 0x26, 0x34, 0x7B, 0x47, 0x81, 0x03,
+ 0x96, 0x3C, 0x55, 0x8A, 0x6E, 0x73, 0x51, 0x88,
+ 0x1B, 0x05, 0x52, 0xDC, 0x8A, 0xA4, 0x07, 0x50,
+ 0x3C, 0x98, 0xC3, 0xFC, 0x58, 0xFA, 0xC8, 0x94,
+ 0x7D, 0x75, 0xE3, 0x4B, 0x6C, 0xCC, 0xB7, 0x9D,
+ 0x6F, 0xEA, 0x79, 0x4F, 0x5C, 0x77, 0xD3, 0x1B,
+ 0xC5, 0xB7, 0x97, 0xD7, 0xD4, 0xE9, 0x72, 0xD5,
+ 0x7E, 0xA3, 0xB5, 0xE9, 0xAC, 0xA0, 0x5D, 0xF8,
+ 0x38, 0xAC, 0x50, 0xA2, 0x47, 0x51, 0x96, 0x15,
+ 0x73, 0x74, 0x1B, 0x4E, 0xF2, 0x80, 0x59, 0xC6,
+ 0x58, 0x40, 0x3F, 0xB3, 0xE5, 0x4C, 0x62, 0x1F,
+ 0x65, 0xD9, 0x16, 0xBF, 0xD5, 0x45, 0x4A, 0x39,
+ 0xCA, 0x5A, 0x8F, 0xD2, 0x77, 0x5D, 0x96, 0x25,
+ 0x2E, 0xD4, 0xC3, 0x01, 0x25, 0xFB, 0x78
+};
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testpoly1305.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testpoly1305.c
new file mode 100644
index 00000000..3ecf1ca8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testpoly1305.c
@@ -0,0 +1,102 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+
+#include "poly1305.h"
+
+#include "testutil.h"
+#include "handy.h"
+#include "cutest.h"
+
+static void check(const char *rstr, const char *sstr,
+ const char *msgstr, const char *tagstr)
+{
+ uint8_t r[16], s[16], tag[16];
+ uint8_t msg[132], out[16];
+
+ unhex(r, sizeof r, rstr);
+ unhex(s, sizeof s, sstr);
+ size_t nmsg = unhex(msg, sizeof msg, msgstr);
+ unhex(tag, sizeof tag, tagstr);
+
+ cf_poly1305 ctx;
+ cf_poly1305_init(&ctx, r, s);
+ cf_poly1305_update(&ctx, msg, nmsg);
+ cf_poly1305_finish(&ctx, out);
+
+ TEST_CHECK(memcmp(out, tag, 16) == 0);
+}
+
+static void test_poly1305(void)
+{
+ check("eea6a7251c1e72916d11c2cb214d3c25",
+ "2539121d8e234e652d651fa4c8cff880",
+ "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5",
+ "f3ffc7703f9400e52a7dfb4b3d3305d9");
+
+ check("851fc40c3467ac0be05cc20404f3f700",
+ "580b3b0f9447bb1e69d095b5928b6dbc",
+ "f3f6",
+ "f4c633c3044fc145f84f335cb81953de");
+
+ check("a0f3080000f46400d0c7e9076c834403",
+ "dd3fab2251f11ac759f0887129cc2ee7",
+ "",
+ "dd3fab2251f11ac759f0887129cc2ee7");
+
+ check("48443d0bb0d21109c89a100b5ce2c208",
+ "83149c69b561dd88298a1798b10716ef",
+ "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
+ "0ee1c16bb73f0f4fd19881753c01cdbe");
+
+ check("12976a08c4426d0ce8a82407c4f48207",
+ "80f8c20aa71202d1e29179cbcb555a57",
+ "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9",
+ "5154ad0d2cb26e01274fc51148491f1b");
+
+ /* extras from RFC7539 */
+ check("02000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "03000000000000000000000000000000");
+ check("02000000000000000000000000000000",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "02000000000000000000000000000000",
+ "03000000000000000000000000000000");
+ check("01000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11000000000000000000000000000000",
+ "05000000000000000000000000000000");
+ check("01000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE01010101010101010101010101010101",
+ "00000000000000000000000000000000");
+ check("02000000000000000000000000000000",
+ "00000000000000000000000000000000",
+ "FDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "FAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+ check("01000000000000000400000000000000",
+ "00000000000000000000000000000000",
+ "E33594D7505E43B900000000000000003394D7505E4379CD01000000000000000000000000000000000000000000000001000000000000000000000000000000",
+ "14000000000000005500000000000000");
+ check("01000000000000000400000000000000",
+ "00000000000000000000000000000000",
+ "E33594D7505E43B900000000000000003394D7505E4379CD010000000000000000000000000000000000000000000000",
+ "13000000000000000000000000000000");
+}
+
+TEST_LIST = {
+ { "poly1305", test_poly1305 },
+ { 0 }
+};
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsalsa20.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsalsa20.c
new file mode 100644
index 00000000..9d50b939
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsalsa20.c
@@ -0,0 +1,210 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "salsa20.h"
+
+#include "testutil.h"
+#include "handy.h"
+#include "cutest.h"
+
+static void test_salsa20_core(void)
+{
+ uint8_t k0[16], k1[16], nonce[16], sigma[16], out[64], expect[64];
+
+ /* From section 8. */
+ memset(k0, 0, sizeof k0);
+ memset(k1, 0, sizeof k1);
+ memset(nonce, 0, sizeof nonce);
+ memset(sigma, 0, sizeof sigma);
+
+ cf_salsa20_core(k0, k1, nonce, sigma, out);
+
+ unhex(expect, 64, "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ /*
+ d39f0d73
+ 4c3752b70375de25bfbbea8831edb330
+ 016ab2db
+ afc7a6305610b3cf1ff0203f0f535da1
+ 74933071
+ ee37cc244fc9eb4f03519c2fcb1af4f3
+ 58766836
+ */
+ unhex(k0, 16, "4c3752b70375de25bfbbea8831edb330");
+ unhex(k1, 16, "ee37cc244fc9eb4f03519c2fcb1af4f3");
+ unhex(nonce, 16, "afc7a6305610b3cf1ff0203f0f535da1");
+ unhex(sigma, 16, "d39f0d73016ab2db7493307158766836");
+
+ cf_salsa20_core(k0, k1, nonce, sigma, out);
+
+ unhex(expect, 64, "6d2ab2a89cf0f8eea8c4becb1a6eaa9a1d1d961a961eebf9bea3fb30459033397628989db4391b5e6b2aec231b6f7272dbece8876f9b6e1218e85f9eb31330ca");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ /*
+ 58766836
+ 4fc9eb4f03519c2fcb1af4f3bfbbea88
+ d39f0d73
+ 4c3752b70375de255610b3cf31edb330
+ 016ab2db
+ afc7a630ee37cc241ff0203f0f535da1
+ 74933071
+ */
+ unhex(k0, 16, "4fc9eb4f03519c2fcb1af4f3bfbbea88");
+ unhex(k1, 16, "afc7a630ee37cc241ff0203f0f535da1");
+ unhex(nonce, 16, "4c3752b70375de255610b3cf31edb330");
+ unhex(sigma, 16, "58766836d39f0d73016ab2db74933071");
+
+ cf_salsa20_core(k0, k1, nonce, sigma, out);
+
+ unhex(expect, 64, "b31330cadbece8876f9b6e1218e85f9e1a6eaa9a6d2ab2a89cf0f8eea8c4becb459033391d1d961a961eebf9bea3fb301b6f72727628989db4391b5e6b2aec23");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ /* From section 9. */
+ for (size_t i = 0; i < 16; i++)
+ {
+ k0[i] = 1 + i;
+ k1[i] = 201 + i;
+ nonce[i] = 101 + i;
+ }
+
+ cf_salsa20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 64, "45254427290f6bc1ff8b7a06aae9d9625990b66a1533c841ef31de22d772287e68c507e1c5991f02664e4cb054f5f6b8b1a0858206489577c0c384ecea67f64a");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ cf_salsa20_core(k0, k0, nonce, (const uint8_t *) "expand 16-byte k", out);
+
+ unhex(expect, 64, "27ad2ef81ec852113043feef25120df7f1c83d900a3732b9062ff6fd8f56bbe186556ef6a1a32bebe75eab3391d6701d0ee80510978cb78dab097ab568b6b1c1");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+}
+
+static void test_salsa20(void)
+{
+ cf_salsa20_ctx ctx;
+ uint8_t key[32], nonce[8], cipher[64], expect[64];
+
+ unhex(key, 32, "0102030405060708090a0b0c0d0e0f10c9cacbcccdcecfd0d1d2d3d4d5d6d7d8");
+ memset(nonce, 0, 8);
+
+ cf_salsa20_init(&ctx, key, sizeof key, nonce);
+ unhex(ctx.nonce, 16, "65666768696a6b6c6d6e6f7071727374");
+ memset(cipher, 0, 64);
+ cf_salsa20_cipher(&ctx, cipher, cipher, 64);
+
+ unhex(expect, 64, "45254427290f6bc1ff8b7a06aae9d9625990b66a1533c841ef31de22d772287e68c507e1c5991f02664e4cb054f5f6b8b1a0858206489577c0c384ecea67f64a");
+ TEST_CHECK(memcmp(expect, cipher, 64) == 0);
+
+ cf_salsa20_init(&ctx, key, 16, nonce);
+ unhex(ctx.nonce, 16, "65666768696a6b6c6d6e6f7071727374");
+ memset(cipher, 0, 64);
+ cf_salsa20_cipher(&ctx, cipher, cipher, 64);
+
+ unhex(expect, 64, "27ad2ef81ec852113043feef25120df7f1c83d900a3732b9062ff6fd8f56bbe186556ef6a1a32bebe75eab3391d6701d0ee80510978cb78dab097ab568b6b1c1");
+ TEST_CHECK(memcmp(expect, cipher, 64) == 0);
+}
+
+static void test_chacha20_core(void)
+{
+ uint8_t k0[16], k1[16], nonce[16], out[64], expect[64];
+
+ /* From draft-agl-tls-chacha20poly1305-04 section 7. */
+
+ memset(k0, 0, sizeof k0);
+ memset(k1, 0, sizeof k1);
+ memset(nonce, 0, sizeof nonce);
+
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 60, "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669");
+ TEST_CHECK(memcmp(expect, out, 60) == 0);
+
+ k1[15] = 0x01;
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 60, "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275");
+ TEST_CHECK(memcmp(expect, out, 60) == 0);
+
+ memset(k1, 0, sizeof k1);
+ nonce[15] = 0x01;
+
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 60, "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3");
+ TEST_CHECK(memcmp(expect, out, 60) == 0);
+
+ memset(nonce, 0, sizeof nonce);
+ nonce[8] = 0x01;
+
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 64, "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ unhex(k0, 16, "000102030405060708090a0b0c0d0e0f");
+ unhex(k1, 16, "101112131415161718191a1b1c1d1e1f");
+ unhex(nonce, 16, "00000000000000000001020304050607");
+
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 64, "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ nonce[0]++;
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 64, "38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c7");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ nonce[0]++;
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 64, "9db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d7");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+
+ nonce[0]++;
+ cf_chacha20_core(k0, k1, nonce, (const uint8_t *) "expand 32-byte k", out);
+
+ unhex(expect, 64, "0eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9");
+ TEST_CHECK(memcmp(expect, out, 64) == 0);
+}
+
+static void test_chacha20(void)
+{
+ uint8_t key[32], nonce[8], block[256], expect[256];
+
+ unhex(key, 32, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+ unhex(nonce, 8, "0001020304050607");
+ unhex(expect, 256, "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9");
+ memset(block, 0, 256);
+
+ cf_chacha20_ctx ctx;
+ cf_chacha20_init(&ctx, key, sizeof key, nonce);
+ cf_chacha20_cipher(&ctx, block, block, sizeof block);
+
+ TEST_CHECK(memcmp(expect, block, sizeof expect) == 0);
+
+ /* Check 128-bit mode works. */
+ cf_chacha20_init(&ctx, key, 16, nonce);
+ cf_chacha20_cipher(&ctx, block, block, sizeof block);
+}
+
+TEST_LIST = {
+ { "salsa20-core", test_salsa20_core },
+ { "chacha20-core", test_chacha20_core },
+ { "salsa20", test_salsa20 },
+ { "chacha20", test_chacha20 },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha.h
new file mode 100644
index 00000000..70075f01
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha.h
@@ -0,0 +1,213 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef TESTSHA_H
+#define TESTSHA_H
+
+#include "hmac.h"
+
+/* Common functions for testing hash functions.
+ * You shouldn't use this file. */
+
+static void vector(const cf_chash *hash,
+ const void *vmsg, size_t nmsg,
+ const char *expect, size_t nexpect)
+{
+ uint8_t digest[CF_MAXHASH];
+ const uint8_t *msg = vmsg;
+ size_t orig_nmsg = nmsg;
+
+ cf_chash_ctx ctx;
+ hash->init(&ctx);
+
+ /* Input in carefully chosen chunk sizes to exercise blockwise code. */
+ if (nmsg)
+ {
+ hash->update(&ctx, msg, 1);
+ nmsg--;
+ msg++;
+ }
+
+ hash->update(&ctx, msg, nmsg);
+ hash->digest(&ctx, digest);
+ TEST_CHECK(nexpect == hash->hashsz);
+ TEST_CHECK(memcmp(digest, expect, nexpect) == 0);
+
+ /* Now try with other arrangements. */
+ msg = vmsg;
+ nmsg = orig_nmsg;
+
+ hash->init(&ctx);
+ if (nmsg >= hash->blocksz)
+ {
+ hash->update(&ctx, msg, hash->blocksz - 1);
+ nmsg -= hash->blocksz - 1;
+ msg += hash->blocksz - 1;
+ }
+
+ hash->update(&ctx, msg, nmsg);
+ hash->digest(&ctx, digest);
+ TEST_CHECK(memcmp(digest, expect, nexpect) == 0);
+}
+
+/* These are shared between RFC2202 and RFC4231. */
+static inline void hmac_test(const cf_chash *hash,
+ const void *hi_there,
+ const void *jefe,
+ const void *aa_dd,
+ const void *counter_key)
+{
+ uint8_t sig[CF_MAXHASH];
+ uint8_t key[25], message[50];
+
+ /* Key: 0x0b * 20
+ * Message: "Hi There"
+ */
+ memset(key, 0x0b, 20);
+ memcpy(message, "Hi There", 8);
+ cf_hmac(key, 20, message, 8, sig, hash);
+
+ TEST_CHECK(memcmp(sig, hi_there, hash->hashsz) == 0);
+
+ /* Key: "Jefe"
+ * Message: "what do ya want for nothing?"
+ */
+ memcpy(key, "Jefe", 4);
+ memcpy(message, "what do ya want for nothing?", 28);
+ cf_hmac(key, 4, message, 28, sig, hash);
+ TEST_CHECK(memcmp(sig, jefe, hash->hashsz) == 0);
+
+ /* Key: 0xaa * 20
+ * Message: 0xdd * 50
+ */
+ memset(key, 0xaa, 20);
+ memset(message, 0xdd, 50);
+ cf_hmac(key, 20, message, 50, sig, hash);
+ TEST_CHECK(memcmp(sig, aa_dd, hash->hashsz) == 0);
+
+ /* Key: 0x01..0x19
+ * Message: 0xcd * 50
+ */
+ for (uint8_t i = 1; i < 26; i++)
+ key[i - 1] = i;
+ memset(message, 0xcd, 50);
+ cf_hmac(key, 25, message, 50, sig, hash);
+ TEST_CHECK(memcmp(sig, counter_key, hash->hashsz) == 0);
+}
+
+/* These are specific to RFC4231. */
+static inline void hmac_test_sha2(const cf_chash *hash,
+ const char *long_key,
+ const char *long_message)
+{
+ uint8_t sig[CF_MAXHASH];
+ uint8_t key[131], message[152];
+
+ /* Key: 0xaa * 131
+ * Message: "Test Using Larger Than Block-Size Key - Hash Key First"
+ */
+ memset(key, 0xaa, 131);
+ memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54);
+ cf_hmac(key, 131, message, 54, sig, hash);
+ TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0);
+
+ /* Key: 0xaa * 131
+ * Message: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ */
+ memset(key, 0xaa, 131);
+ memcpy(message, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", 152);
+ cf_hmac(key, 131, message, 152, sig, hash);
+ TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0);
+}
+
+/* This is as hmac_test_sha2, except the sizes are specific to
+ * a 512-bit block. This is from RFC2202. */
+static inline void hmac_test_sha1(const cf_chash *hash,
+ const char *long_key,
+ const char *long_message)
+{
+ uint8_t sig[CF_MAXHASH];
+ uint8_t key[80], message[73];
+
+ /* Key: 0xaa * 80
+ * Message: "Test Using Larger Than Block-Size Key - Hash Key First"
+ */
+ memset(key, 0xaa, 80);
+ memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54);
+ cf_hmac(key, 80, message, 54, sig, hash);
+ TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0);
+
+ /* Key: 0xaa * 80
+ * Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+ */
+ memset(key, 0xaa, 80);
+ memcpy(message, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73);
+ cf_hmac(key, 80, message, 73, sig, hash);
+ TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0);
+}
+
+typedef void (*final_fn)(void *ctx, uint8_t *out);
+
+/* Check incremental interface works, and final function likewise. */
+static void vector_abc_final(const cf_chash *hash, const void *vfinal_fn,
+ const void *expect, size_t nexpect)
+{
+ uint8_t digest[CF_MAXHASH];
+
+ final_fn final = vfinal_fn;
+ cf_chash_ctx ctx;
+ hash->init(&ctx);
+ hash->update(&ctx, "a", 1);
+ hash->digest(&ctx, digest);
+ hash->update(&ctx, "b", 1);
+ hash->digest(&ctx, digest);
+ hash->update(&ctx, "c", 1);
+ final(&ctx, digest);
+
+ TEST_CHECK(hash->hashsz == nexpect);
+ TEST_CHECK(memcmp(expect, digest, nexpect) == 0);
+}
+
+/* Check length-checking vectors work (generated by programs in ../extra_vecs) */
+static inline void vector_length(const cf_chash *h,
+ size_t max,
+ const void *expect, size_t nexpect)
+{
+ cf_chash_ctx outer, inner;
+ uint8_t digest[CF_MAXHASH];
+
+ h->init(&outer);
+
+ for (size_t n = 0; n < max; n++)
+ {
+ h->init(&inner);
+
+ for (size_t i = 0; i < n; i++)
+ {
+ uint8_t byte = (uint8_t) n & 0xff;
+ h->update(&inner, &byte, 1);
+ }
+
+ h->digest(&inner, digest);
+
+ h->update(&outer, digest, h->hashsz);
+ }
+
+ h->digest(&outer, digest);
+
+ TEST_CHECK(h->hashsz == nexpect);
+ TEST_CHECK(memcmp(expect, digest, nexpect) == 0);
+}
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha1.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha1.c
new file mode 100644
index 00000000..c7adc8a4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha1.c
@@ -0,0 +1,55 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "sha1.h"
+#include "hmac.h"
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+#include "testsha.h"
+
+static void test_sha1(void)
+{
+ const cf_chash *h = &cf_sha1;
+ vector(h, "", 0, "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09", 20);
+ vector(h, "abc", 3, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20);
+ vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1", 20);
+ vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\xa4\x9b\x24\x46\xa0\x2c\x64\x5b\xf4\x19\xf9\x95\xb6\x70\x91\x25\x3a\x04\xa2\x59", 20);
+
+ vector_abc_final(h, cf_sha1_digest_final, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d", 20);
+
+ vector_length(h, 1024, "\x15\x53\x65\xcf\x77\xee\xd4\x8f\x46\xe2\x55\xc7\xdd\xdf\xfd\x0a\xf6\x99\x88\xbe", 20);
+}
+
+static void test_hmac_sha1(void)
+{
+ hmac_test(&cf_sha1,
+ "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00",
+ "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79",
+ "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3",
+ "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda");
+ hmac_test_sha1(&cf_sha1,
+ "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55\xed\x40\x21\x12",
+ "\xe8\xe9\x9d\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08\xbb\xff\x1a\x91");
+}
+
+TEST_LIST = {
+ { "sha1", test_sha1},
+ { "hmac-sha1", test_hmac_sha1},
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha2.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha2.c
new file mode 100644
index 00000000..fc0ab6c8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha2.c
@@ -0,0 +1,224 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "sha2.h"
+#include "hmac.h"
+#include "pbkdf2.h"
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+
+#include "testsha.h"
+
+#undef REALLY_SLOW_TEST
+
+static void test_sha224(void)
+{
+ const cf_chash *h = &cf_sha224;
+ vector(h, "", 0, "\xd1\x4a\x02\x8c\x2a\x3a\x2b\xc9\x47\x61\x02\xbb\x28\x82\x34\xc4\x15\xa2\xb0\x1f\x82\x8e\xa6\x2a\xc5\xb3\xe4\x2f", 28);
+ vector(h, "abc", 3, "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28);
+ vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x75\x38\x8b\x16\x51\x27\x76\xcc\x5d\xba\x5d\xa1\xfd\x89\x01\x50\xb0\xc6\x45\x5c\xb4\xf5\x8b\x19\x52\x52\x25\x25", 28);
+ vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\xc9\x7c\xa9\xa5\x59\x85\x0c\xe9\x7a\x04\xa9\x6d\xef\x6d\x99\xa9\xe0\xe0\xe2\xab\x14\xe6\xb8\xdf\x26\x5f\xc0\xb3", 28);
+
+ /* Check that incremental interface produces correct results. */
+ vector_abc_final(h, cf_sha224_digest_final, "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7", 28);
+
+ vector_length(h, 1024, "\x08\x2c\x80\x5b\x6f\x85\xde\x0e\xdf\xa8\x51\xa0\x1f\xe6\x4f\x64\x85\x16\x48\xae\xfc\xc1\xd4\x52\x4e\xf8\x36\xe7", 28);
+}
+
+static void test_hmac_sha224(void)
+{
+ hmac_test(&cf_sha224,
+ "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22",
+ "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44",
+ "\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea",
+ "\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a");
+ hmac_test_sha2(&cf_sha224,
+ "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e",
+ "\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1");
+}
+
+static void test_sha256(void)
+{
+ const cf_chash *h = &cf_sha256;
+ vector(h, "", 0, "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55", 32);
+ vector(h, "abc", 3, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32);
+ vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1", 32);
+ vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\xcf\x5b\x16\xa7\x78\xaf\x83\x80\x03\x6c\xe5\x9e\x7b\x04\x92\x37\x0b\x24\x9b\x11\xe8\xf0\x7a\x51\xaf\xac\x45\x03\x7a\xfe\xe9\xd1", 32);
+
+ vector_abc_final(h, cf_sha256_digest_final, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad", 32);
+
+ vector_length(h, 1024, "\x55\x7b\xfd\xd5\xef\xda\xfd\x63\x06\x5e\xb7\x98\x87\xde\x86\xdb\x54\xc3\xfe\xdf\x7b\xcc\xcb\x97\x08\xfa\x87\xf0\x11\x87\x61\xdc", 32);
+}
+
+static void test_hmac_sha256(void)
+{
+ hmac_test(&cf_sha256,
+ "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7",
+ "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43",
+ "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe",
+ "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b");
+ hmac_test_sha2(&cf_sha256,
+ "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54",
+ "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2");
+}
+
+static void test_sha384(void)
+{
+ const cf_chash *h = &cf_sha384;
+ vector(h, "", 0, "\x38\xb0\x60\xa7\x51\xac\x96\x38\x4c\xd9\x32\x7e\xb1\xb1\xe3\x6a\x21\xfd\xb7\x11\x14\xbe\x07\x43\x4c\x0c\xc7\xbf\x63\xf6\xe1\xda\x27\x4e\xde\xbf\xe7\x6f\x65\xfb\xd5\x1a\xd2\xf1\x48\x98\xb9\x5b", 48);
+ vector(h, "abc", 3, "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48);
+ vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x33\x91\xfd\xdd\xfc\x8d\xc7\x39\x37\x07\xa6\x5b\x1b\x47\x09\x39\x7c\xf8\xb1\xd1\x62\xaf\x05\xab\xfe\x8f\x45\x0d\xe5\xf3\x6b\xc6\xb0\x45\x5a\x85\x20\xbc\x4e\x6f\x5f\xe9\x5b\x1f\xe3\xc8\x45\x2b", 48);
+ vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91\x74\x60\x39", 48);
+
+ vector_abc_final(h, cf_sha384_digest_final, "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7", 48);
+
+ vector_length(h, 1024, "\xae\xe7\xf1\x43\xef\x69\x7b\xa2\xe1\xfd\x39\x9f\xd7\xe6\x28\x9c\x19\xaf\x3c\xc1\xbd\xda\xbd\x3f\x07\xae\xc2\xea\x40\x55\x37\x27\x5f\x41\x49\x50\x3f\xcc\xaf\xa0\xc5\x95\xf7\x62\x9b\xff\x50\x32", 48);
+}
+
+static void test_hmac_sha384(void)
+{
+ hmac_test(&cf_sha384,
+ "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6",
+ "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49",
+ "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27",
+ "\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb");
+ hmac_test_sha2(&cf_sha384,
+ "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52",
+ "\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e");
+}
+
+static void test_sha512(void)
+{
+ const cf_chash *h = &cf_sha512;
+ vector(h, "", 0, "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e", 64);
+ vector(h, "abc", 3, "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f", 64);
+ vector(h, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45", 64);
+ vector(h, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09", 64);
+
+ vector_abc_final(h, cf_sha512_digest_final, "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f", 64);
+
+ vector_length(h, 1024, "\x61\x20\x81\x2e\xd5\x0c\xc3\x11\x67\x04\x3f\x1f\x06\x9d\xcd\x4a\xd8\x83\x23\xd9\x96\x53\xd9\x67\x38\x2c\xc3\x44\x25\x69\x53\x1c\xd0\x3d\xe4\x79\x0a\x71\xde\x88\x45\x44\x66\x80\xb8\xc5\x90\xb3\x07\xc8\xae\x52\x57\x67\xf9\x28\xf8\xda\x9e\x9e\x80\xc9\x35\x5e", 64);
+}
+
+static void test_hmac_sha512(void)
+{
+ hmac_test(&cf_sha512,
+ "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54",
+ "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37",
+ "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb",
+ "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd");
+ hmac_test_sha2(&cf_sha512,
+ "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98",
+ "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58");
+}
+
+#ifdef REALLY_SLOW_TEST
+static void test_sha256_long(void)
+{
+ uint8_t digest[32];
+ cf_sha256_context ctx;
+ cf_sha256_init(&ctx);
+
+ for (size_t i = 0; i < 0x1000000; i++)
+ cf_sha256_update(&ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno", 64);
+ cf_sha256_digest_final(&ctx, digest);
+
+ uint8_t expect[32];
+ unhex(expect, sizeof expect, "\x50\xe7\x2a\x0e\x26\x44\x2f\xe2\x55\x2d\xc3\x93\x8a\xc5\x86\x58\x22\x8c\x0c\xbf\xb1\xd2\xca\x87\x2a\xe4\x35\x26\x6f\xcd\x05\x5e", 32);
+ TEST_CHECK(memcmp(expect, digest, sizeof digest) == 0);
+}
+#endif
+
+static void check_pkbdf2_sha256(const void *pw, size_t npw,
+ const void *salt, size_t nsalt,
+ uint32_t iters,
+ const void *expect, size_t nexpect)
+{
+ uint8_t output[64];
+
+ cf_pbkdf2_hmac((const void *) pw, npw,
+ (const void *) salt, nsalt,
+ iters,
+ output, nexpect,
+ &cf_sha256);
+
+ TEST_CHECK(memcmp(expect, output, nexpect) == 0);
+}
+
+static void test_pbkdf2_sha256(void)
+{
+ check_pkbdf2_sha256("password", 8,
+ "salt", 4,
+ 1,
+ "\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52\x56\xc4\xf8\x37\xa8\x65\x48\xc9\x2c\xcc\x35\x48\x08\x05\x98\x7c\xb7\x0b\xe1\x7b", 32);
+
+ check_pkbdf2_sha256("password", 8,
+ "salt", 4,
+ 2,
+ "\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e\xf3\xc2\x51\xdf\xd6\xe2\xd8\x5a\x95\x47\x4c\x43", 32);
+
+ check_pkbdf2_sha256("password", 8,
+ "salt", 4,
+ 4096,
+ "\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6\x84\x5c\x4c\x8d\x96\x28\x93\xa0\x01\xce\x4e\x11\xa4\x96\x38\x73\xaa\x98\x13\x4a", 32);
+
+ check_pkbdf2_sha256("passwordPASSWORDpassword", 24,
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+ 4096,
+ "\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c\x4e\x2a\x1f\xb8\xdd\x53\xe1\xc6\x35\x51\x8c\x7d\xac\x47\xe9", 40);
+
+ check_pkbdf2_sha256("", 0,
+ "salt", 4,
+ 1024,
+ "\x9e\x83\xf2\x79\xc0\x40\xf2\xa1\x1a\xa4\xa0\x2b\x24\xc4\x18\xf2\xd3\xcb\x39\x56\x0c\x96\x27\xfa\x4f\x47\xe3\xbc\xc2\x89\x7c\x3d", 32);
+
+ check_pkbdf2_sha256("password", 8,
+ "", 0,
+ 1024,
+ "\xea\x58\x08\x41\x1e\xb0\xc7\xe8\x30\xde\xab\x55\x09\x6c\xee\x58\x27\x61\xe2\x2a\x9b\xc0\x34\xe3\xec\xe9\x25\x22\x5b\x07\xbf\x46", 32);
+
+ check_pkbdf2_sha256("\x70\x61\x73\x73\x00\x77\x6f\x72\x64", 9,
+ "\x73\x61\x00\x6c\x74", 5,
+ 4096,
+ "\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65\x0a\x86\x87", 16);
+}
+
+TEST_LIST = {
+ { "sha224", test_sha224},
+ { "sha256", test_sha256 },
+ { "sha384", test_sha384 },
+ { "sha512", test_sha512 },
+
+ { "hmac-sha224", test_hmac_sha224 },
+ { "hmac-sha256", test_hmac_sha256 },
+ { "hmac-sha384", test_hmac_sha384 },
+ { "hmac-sha512", test_hmac_sha512 },
+
+ { "pbkdf2-sha256", test_pbkdf2_sha256 },
+
+#ifdef REALLY_SLOW_TEST
+ { "sha256-long", test_sha256_long },
+#endif
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha3.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha3.c
new file mode 100644
index 00000000..92ab9cf0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testsha3.c
@@ -0,0 +1,104 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include "sha3.h"
+#include "handy.h"
+#include "cutest.h"
+#include "testutil.h"
+#include "testsha.h"
+
+static void test_sha3_224(void)
+{
+ const cf_chash *H = &cf_sha3_224;
+ vector(H, "", 0,
+ "\x6b\x4e\x03\x42\x36\x67\xdb\xb7\x3b\x6e\x15\x45\x4f\x0e\xb1\xab\xd4\x59\x7f\x9a\x1b\x07\x8e\x3f\x5b\x5a\x6b\xc7", 28);
+ vector(H, "abc", 3,
+ "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf", 28);
+ vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x8a\x24\x10\x8b\x15\x4a\xda\x21\xc9\xfd\x55\x74\x49\x44\x79\xba\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea\xd0\xfc\xce\x33", 28);
+ vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc", 28);
+
+ /* Artificial exercise for len(msg) = rate_bytes - 1 codepath */
+ vector(H, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 143,
+ "\x73\xb1\xb2\x2b\x54\xf5\x15\xf6\x26\xa6\xab\xdd\xe6\xaf\x25\xcd\x48\x01\xdc\x6e\x9d\xc7\xfa\x3f\x77\xe1\xc1\x22", 28);
+
+ vector_abc_final(H, cf_sha3_224_digest_final,
+ "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf", 28);
+
+ vector_length(H, 1024, "\xf2\x54\xf3\x67\x6d\xc6\xc0\x0f\x2f\xee\x50\x59\x07\x62\x8b\x0d\x5b\x9e\xdf\xf8\xe8\xc2\x9e\x9b\xa7\xd6\x05\xdd", 28);
+}
+
+static void test_sha3_256(void)
+{
+ const cf_chash *H = &cf_sha3_256;
+ vector(H, "", 0,
+ "\xa7\xff\xc6\xf8\xbf\x1e\xd7\x66\x51\xc1\x47\x56\xa0\x61\xd6\x62\xf5\x80\xff\x4d\xe4\x3b\x49\xfa\x82\xd8\x0a\x4b\x80\xf8\x43\x4a", 32);
+ vector(H, "abc", 3,
+ "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32", 32);
+ vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x41\xc0\xdb\xa2\xa9\xd6\x24\x08\x49\x10\x03\x76\xa8\x23\x5e\x2c\x82\xe1\xb9\x99\x8a\x99\x9e\x21\xdb\x32\xdd\x97\x49\x6d\x33\x76", 32);
+ vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18", 32);
+
+ vector_abc_final(H, cf_sha3_256_digest_final,
+ "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32", 32);
+
+ vector_length(H, 1024, "\xf7\xed\xf7\x2b\x34\x8c\xb4\xab\x5e\xe7\x4f\x6c\xae\xaf\x11\xad\xe2\x2f\x04\x65\x84\x8e\x5c\xaa\x14\x38\x7f\xd4\xeb\xdb\x9d\x70", 32);
+}
+
+static void test_sha3_384(void)
+{
+ const cf_chash *H = &cf_sha3_384;
+ vector(H, "", 0,
+ "\x0c\x63\xa7\x5b\x84\x5e\x4f\x7d\x01\x10\x7d\x85\x2e\x4c\x24\x85\xc5\x1a\x50\xaa\xaa\x94\xfc\x61\x99\x5e\x71\xbb\xee\x98\x3a\x2a\xc3\x71\x38\x31\x26\x4a\xdb\x47\xfb\x6b\xd1\xe0\x58\xd5\xf0\x04", 48);
+ vector(H, "abc", 3,
+ "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25", 48);
+ vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x99\x1c\x66\x57\x55\xeb\x3a\x4b\x6b\xbd\xfb\x75\xc7\x8a\x49\x2e\x8c\x56\xa2\x2c\x5c\x4d\x7e\x42\x9b\xfd\xbc\x32\xb9\xd4\xad\x5a\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1\x9e\xef\x51\xac\xd0\x65\x7c\x22", 48);
+ vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7", 48);
+
+ vector_abc_final(H, cf_sha3_384_digest_final,
+ "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25", 48);
+
+ vector_length(H, 1024, "\xc2\x16\x48\x6a\x00\x32\xb1\xe1\x98\xf8\x72\x52\x01\x87\xba\xd4\xcf\x39\x13\x9c\x54\x21\x6d\x78\x86\x93\x88\xf9\x75\x03\xc1\x11\xcc\x7f\x5a\xc3\x21\x00\x3f\xc8\xa1\xf7\xfa\x10\x75\x60\xdb\xb1", 48);
+}
+
+static void test_sha3_512(void)
+{
+ const cf_chash *H = &cf_sha3_512;
+ vector(H, "", 0,
+ "\xa6\x9f\x73\xcc\xa2\x3a\x9a\xc5\xc8\xb5\x67\xdc\x18\x5a\x75\x6e\x97\xc9\x82\x16\x4f\xe2\x58\x59\xe0\xd1\xdc\xc1\x47\x5c\x80\xa6\x15\xb2\x12\x3a\xf1\xf5\xf9\x4c\x11\xe3\xe9\x40\x2c\x3a\xc5\x58\xf5\x00\x19\x9d\x95\xb6\xd3\xe3\x01\x75\x85\x86\x28\x1d\xcd\x26", 64);
+ vector(H, "abc", 3,
+ "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0", 64);
+ vector(H, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+ "\x04\xa3\x71\xe8\x4e\xcf\xb5\xb8\xb7\x7c\xb4\x86\x10\xfc\xa8\x18\x2d\xd4\x57\xce\x6f\x32\x6a\x0f\xd3\xd7\xec\x2f\x1e\x91\x63\x6d\xee\x69\x1f\xbe\x0c\x98\x53\x02\xba\x1b\x0d\x8d\xc7\x8c\x08\x63\x46\xb5\x33\xb4\x9c\x03\x0d\x99\xa2\x7d\xaf\x11\x39\xd6\xe7\x5e", 64);
+ vector(H, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+ "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85", 64);
+
+ vector_abc_final(H, cf_sha3_512_digest_final,
+ "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0", 64);
+
+ vector_length(H, 1024, "\x3a\x98\x11\x17\xbc\x2f\xa3\x3b\x00\x51\x71\xf8\x80\x86\x33\x7f\x4f\x6c\xe9\xd1\x5c\xb7\x38\xc0\x9b\xe2\x8a\xb6\xd5\x38\xba\xbf\x7b\xc5\x4e\xbf\x3d\xdb\x53\x4a\x9c\x3c\x10\x85\xe7\x18\x3d\x46\xa5\x8c\xbc\xb0\x15\xb0\xdf\x50\x7a\xad\x0e\xdf\xf3\x54\x8e\xfd", 64);
+}
+
+TEST_LIST = {
+ { "sha3-224", test_sha3_224 },
+ { "sha3-256", test_sha3_256 },
+ { "sha3-384", test_sha3_384 },
+ { "sha3-512", test_sha3_512 },
+ { 0 }
+};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testutil.h b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testutil.h
new file mode 100644
index 00000000..b9a52b33
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/testutil.h
@@ -0,0 +1,61 @@
+/*
+ * cifra - embedded cryptography library
+ * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to the
+ * public domain worldwide. This software is distributed without any
+ * warranty.
+ *
+ * You should have received a copy of the CC0 Public Domain Dedication
+ * along with this software. If not, see
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#ifndef TESTUTIL_H
+#define TESTUTIL_H
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+static inline uint8_t unhex_chr(char a)
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ return 0;
+}
+
+static inline size_t unhex(uint8_t *buf, size_t len, const char *str)
+{
+ size_t used = 0;
+
+ assert(strlen(str) % 2 == 0);
+ assert(strlen(str) / 2 <= len);
+
+ while (*str)
+ {
+ assert(len);
+ *buf = unhex_chr(str[0]) << 4 | unhex_chr(str[1]);
+ buf++;
+ used++;
+ str += 2;
+ len--;
+ }
+
+ return used;
+}
+
+static inline void dump(const char *label, const uint8_t *buf, size_t len)
+{
+ printf("%s: ", label);
+ for (size_t i = 0; i < len; i++)
+ printf("%02x", buf[i]);
+ printf("\n");
+}
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/.gitignore b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/.gitignore
new file mode 100644
index 00000000..cd812eb9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/.gitignore
@@ -0,0 +1,8 @@
+__build__/
+__pycache__
+*.pyc
+*.pyo
+*.pyd
+*.pyz
+*.egg-info/
+.DS_Store \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/LICENSE.txt b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/LICENSE.txt
new file mode 100644
index 00000000..ab099ae5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/LICENSE.txt
@@ -0,0 +1,21 @@
+Copyright (c) 2014, Kenneth MacKay
+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.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(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/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/README.md b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/README.md
new file mode 100644
index 00000000..01926e3f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/README.md
@@ -0,0 +1,41 @@
+micro-ecc
+==========
+
+A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors.
+
+The static version of micro-ecc (ie, where the curve was selected at compile-time) can be found in the "static" branch.
+
+Features
+--------
+
+ * Resistant to known side-channel attacks.
+ * Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms.
+ * Supports 8, 32, and 64-bit architectures.
+ * Small code size.
+ * No dynamic memory allocation.
+ * Support for 5 standard curves: secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1.
+ * BSD 2-clause license.
+
+Usage Notes
+-----------
+### Point Representation ###
+Compressed points are represented in the standard format as defined in http://www.secg.org/collateral/sec1_final.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_compress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations.
+
+Private keys are represented in the standard format.
+
+### Using the Code ###
+
+I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions.
+
+For use with Arduino, you can just create a symlink to the `uECC` directory in your Arduino `libraries` directory. You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu).
+
+See uECC.h for documentation for each function.
+
+### Compilation Notes ###
+
+ * Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013).
+ * If you want to change the defaults for any of the uECC compile-time options (such as `uECC_OPTIMIZATION_LEVEL`), you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_OPTIMIZATION_LEVEL=3` or whatever).
+ * When compiling for a Thumb-1 platform, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
+ * When compiling for an ARM/Thumb-2 platform with `uECC_OPTIMIZATION_LEVEL` >= 3, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher).
+ * When compiling for AVR, you must have optimizations enabled (compile with `-O1` or higher).
+ * When building for Windows, you will need to link in the `advapi32.lib` system library.
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm.inc
new file mode 100644
index 00000000..688fdc75
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm.inc
@@ -0,0 +1,820 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_ASM_ARM_H_
+#define _UECC_ASM_ARM_H_
+
+#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ #define uECC_MIN_WORDS 8
+#endif
+#if uECC_SUPPORTS_secp224r1
+ #undef uECC_MIN_WORDS
+ #define uECC_MIN_WORDS 7
+#endif
+#if uECC_SUPPORTS_secp192r1
+ #undef uECC_MIN_WORDS
+ #define uECC_MIN_WORDS 6
+#endif
+#if uECC_SUPPORTS_secp160r1
+ #undef uECC_MIN_WORDS
+ #define uECC_MIN_WORDS 5
+#endif
+
+#if (uECC_PLATFORM == uECC_arm_thumb)
+ #define REG_RW "+l"
+ #define REG_WRITE "=l"
+#else
+ #define REG_RW "+r"
+ #define REG_WRITE "=r"
+#endif
+
+#if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2)
+ #define REG_RW_LO "+l"
+ #define REG_WRITE_LO "=l"
+#else
+ #define REG_RW_LO "+r"
+ #define REG_WRITE_LO "=r"
+#endif
+
+#if (uECC_PLATFORM == uECC_arm_thumb2)
+ #define RESUME_SYNTAX
+#else
+ #define RESUME_SYNTAX ".syntax divided \n\t"
+#endif
+
+#if (uECC_OPTIMIZATION_LEVEL >= 2)
+
+uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
+ uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
+ #else /* ARM */
+ uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
+ #endif
+#endif
+ uint32_t carry;
+ uint32_t left_word;
+ uint32_t right_word;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ "movs %[carry], #0 \n\t"
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "adr %[left], 1f \n\t"
+ ".align 4 \n\t"
+ "adds %[jump], %[left] \n\t"
+ #endif
+
+ "ldmia %[lptr]!, {%[left]} \n\t"
+ "ldmia %[rptr]!, {%[right]} \n\t"
+ "adds %[left], %[right] \n\t"
+ "stmia %[dptr]!, {%[left]} \n\t"
+
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "bx %[jump] \n\t"
+ #endif
+ "1: \n\t"
+ REPEAT(DEC(uECC_MAX_WORDS),
+ "ldmia %[lptr]!, {%[left]} \n\t"
+ "ldmia %[rptr]!, {%[right]} \n\t"
+ "adcs %[left], %[right] \n\t"
+ "stmia %[dptr]!, {%[left]} \n\t")
+
+ "adcs %[carry], %[carry] \n\t"
+ RESUME_SYNTAX
+ : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ [jump] REG_RW_LO (jump),
+ #endif
+ [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
+ [right] REG_WRITE_LO (right_word)
+ :
+ : "cc", "memory"
+ );
+ return carry;
+}
+#define asm_add 1
+
+uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+#if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2)
+ uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1;
+ #else /* ARM */
+ uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4;
+ #endif
+#endif
+ uint32_t carry;
+ uint32_t left_word;
+ uint32_t right_word;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ "movs %[carry], #0 \n\t"
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "adr %[left], 1f \n\t"
+ ".align 4 \n\t"
+ "adds %[jump], %[left] \n\t"
+ #endif
+
+ "ldmia %[lptr]!, {%[left]} \n\t"
+ "ldmia %[rptr]!, {%[right]} \n\t"
+ "subs %[left], %[right] \n\t"
+ "stmia %[dptr]!, {%[left]} \n\t"
+
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "bx %[jump] \n\t"
+ #endif
+ "1: \n\t"
+ REPEAT(DEC(uECC_MAX_WORDS),
+ "ldmia %[lptr]!, {%[left]} \n\t"
+ "ldmia %[rptr]!, {%[right]} \n\t"
+ "sbcs %[left], %[right] \n\t"
+ "stmia %[dptr]!, {%[left]} \n\t")
+
+ "adcs %[carry], %[carry] \n\t"
+ RESUME_SYNTAX
+ : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right),
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ [jump] REG_RW_LO (jump),
+ #endif
+ [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word),
+ [right] REG_WRITE_LO (right_word)
+ :
+ : "cc", "memory"
+ );
+ return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
+ (for some reason...) */
+}
+#define asm_sub 1
+
+#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
+
+#if (uECC_OPTIMIZATION_LEVEL >= 3)
+
+#if (uECC_PLATFORM != uECC_arm_thumb)
+
+#if uECC_ARM_USE_UMAAL
+ #include "asm_arm_mult_square_umaal.inc"
+#else
+ #include "asm_arm_mult_square.inc"
+#endif
+
+#if (uECC_OPTIMIZATION_LEVEL == 3)
+
+uECC_VLI_API void uECC_vli_mult(uint32_t *result,
+ const uint32_t *left,
+ const uint32_t *right,
+ wordcount_t num_words) {
+ register uint32_t *r0 __asm__("r0") = result;
+ register const uint32_t *r1 __asm__("r1") = left;
+ register const uint32_t *r2 __asm__("r2") = right;
+ register uint32_t r3 __asm__("r3") = num_words;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+#if (uECC_MIN_WORDS == 5)
+ FAST_MULT_ASM_5
+ #if (uECC_MAX_WORDS > 5)
+ FAST_MULT_ASM_5_TO_6
+ #endif
+ #if (uECC_MAX_WORDS > 6)
+ FAST_MULT_ASM_6_TO_7
+ #endif
+ #if (uECC_MAX_WORDS > 7)
+ FAST_MULT_ASM_7_TO_8
+ #endif
+#elif (uECC_MIN_WORDS == 6)
+ FAST_MULT_ASM_6
+ #if (uECC_MAX_WORDS > 6)
+ FAST_MULT_ASM_6_TO_7
+ #endif
+ #if (uECC_MAX_WORDS > 7)
+ FAST_MULT_ASM_7_TO_8
+ #endif
+#elif (uECC_MIN_WORDS == 7)
+ FAST_MULT_ASM_7
+ #if (uECC_MAX_WORDS > 7)
+ FAST_MULT_ASM_7_TO_8
+ #endif
+#elif (uECC_MIN_WORDS == 8)
+ FAST_MULT_ASM_8
+#endif
+ "1: \n\t"
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1), "+r" (r2)
+ : "r" (r3)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+}
+#define asm_mult 1
+
+#if uECC_SQUARE_FUNC
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+ register uint32_t *r0 __asm__("r0") = result;
+ register const uint32_t *r1 __asm__("r1") = left;
+ register uint32_t r2 __asm__("r2") = num_words;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+#if (uECC_MIN_WORDS == 5)
+ FAST_SQUARE_ASM_5
+ #if (uECC_MAX_WORDS > 5)
+ FAST_SQUARE_ASM_5_TO_6
+ #endif
+ #if (uECC_MAX_WORDS > 6)
+ FAST_SQUARE_ASM_6_TO_7
+ #endif
+ #if (uECC_MAX_WORDS > 7)
+ FAST_SQUARE_ASM_7_TO_8
+ #endif
+#elif (uECC_MIN_WORDS == 6)
+ FAST_SQUARE_ASM_6
+ #if (uECC_MAX_WORDS > 6)
+ FAST_SQUARE_ASM_6_TO_7
+ #endif
+ #if (uECC_MAX_WORDS > 7)
+ FAST_SQUARE_ASM_7_TO_8
+ #endif
+#elif (uECC_MIN_WORDS == 7)
+ FAST_SQUARE_ASM_7
+ #if (uECC_MAX_WORDS > 7)
+ FAST_SQUARE_ASM_7_TO_8
+ #endif
+#elif (uECC_MIN_WORDS == 8)
+ FAST_SQUARE_ASM_8
+#endif
+
+ "1: \n\t"
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1)
+ : "r" (r2)
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+}
+#define asm_square 1
+#endif /* uECC_SQUARE_FUNC */
+
+#else /* (uECC_OPTIMIZATION_LEVEL > 3) */
+
+uECC_VLI_API void uECC_vli_mult(uint32_t *result,
+ const uint32_t *left,
+ const uint32_t *right,
+ wordcount_t num_words) {
+ register uint32_t *r0 __asm__("r0") = result;
+ register const uint32_t *r1 __asm__("r1") = left;
+ register const uint32_t *r2 __asm__("r2") = right;
+ register uint32_t r3 __asm__("r3") = num_words;
+
+#if uECC_SUPPORTS_secp160r1
+ if (num_words == 5) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_MULT_ASM_5
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1), "+r" (r2)
+ : "r" (r3)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+#if uECC_SUPPORTS_secp192r1
+ if (num_words == 6) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_MULT_ASM_6
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1), "+r" (r2)
+ : "r" (r3)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+#if uECC_SUPPORTS_secp224r1
+ if (num_words == 7) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_MULT_ASM_7
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1), "+r" (r2)
+ : "r" (r3)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ if (num_words == 8) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_MULT_ASM_8
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1), "+r" (r2)
+ : "r" (r3)
+ : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+}
+#define asm_mult 1
+
+#if uECC_SQUARE_FUNC
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+ register uint32_t *r0 __asm__("r0") = result;
+ register const uint32_t *r1 __asm__("r1") = left;
+ register uint32_t r2 __asm__("r2") = num_words;
+
+#if uECC_SUPPORTS_secp160r1
+ if (num_words == 5) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_SQUARE_ASM_5
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1)
+ : "r" (r2)
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+#if uECC_SUPPORTS_secp192r1
+ if (num_words == 6) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_SQUARE_ASM_6
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1)
+ : "r" (r2)
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+#if uECC_SUPPORTS_secp224r1
+ if (num_words == 7) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_SQUARE_ASM_7
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1)
+ : "r" (r2)
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ if (num_words == 8) {
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ FAST_SQUARE_ASM_8
+ RESUME_SYNTAX
+ : "+r" (r0), "+r" (r1)
+ : "r" (r2)
+ : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+ return;
+ }
+#endif
+}
+#define asm_square 1
+#endif /* uECC_SQUARE_FUNC */
+
+#endif /* (uECC_OPTIMIZATION_LEVEL > 3) */
+
+#endif /* uECC_PLATFORM != uECC_arm_thumb */
+
+#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */
+
+/* ---- "Small" implementations ---- */
+
+#if !asm_add
+uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uint32_t carry = 0;
+ uint32_t left_word;
+ uint32_t right_word;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ "1: \n\t"
+ "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
+ "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
+ "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
+ "adcs %[left], %[left], %[right] \n\t" /* Add with carry. */
+ "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
+ "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
+ "subs %[ctr], #1 \n\t" /* Decrement counter. */
+ "bne 1b \n\t" /* Loop until counter == 0. */
+ RESUME_SYNTAX
+ : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
+ [ctr] REG_RW (num_words), [carry] REG_RW (carry),
+ [left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
+ :
+ : "cc", "memory"
+ );
+ return carry;
+}
+#define asm_add 1
+#endif
+
+#if !asm_sub
+uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
+ uint32_t left_word;
+ uint32_t right_word;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ "1: \n\t"
+ "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
+ "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
+ "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */
+ "sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */
+ "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */
+ "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
+ "subs %[ctr], #1 \n\t" /* Decrement counter. */
+ "bne 1b \n\t" /* Loop until counter == 0. */
+ RESUME_SYNTAX
+ : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
+ [ctr] REG_RW (num_words), [carry] REG_RW (carry),
+ [left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
+ :
+ : "cc", "memory"
+ );
+ return !carry;
+}
+#define asm_sub 1
+#endif
+
+#if !asm_mult
+uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+#if (uECC_PLATFORM != uECC_arm_thumb)
+ uint32_t c0 = 0;
+ uint32_t c1 = 0;
+ uint32_t c2 = 0;
+ uint32_t k = 0;
+ uint32_t i;
+ uint32_t t0, t1;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+
+ "1: \n\t" /* outer loop (k < num_words) */
+ "movs %[i], #0 \n\t" /* i = 0 */
+ "b 3f \n\t"
+
+ "2: \n\t" /* outer loop (k >= num_words) */
+ "movs %[i], %[k] \n\t" /* i = k */
+ "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
+
+ "3: \n\t" /* inner loop */
+ "subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
+
+ "ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */
+ "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
+
+ "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
+
+ "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
+ "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
+ "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
+
+ "adds %[i], #4 \n\t" /* i += 4 */
+ "cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
+ "bgt 4f \n\t" /* if so, exit the loop */
+ "cmp %[i], %[k] \n\t" /* i <= k? */
+ "ble 3b \n\t" /* if so, continue looping */
+
+ "4: \n\t" /* end inner loop */
+
+ "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
+ "mov %[c0], %[c1] \n\t" /* c0 = c1 */
+ "mov %[c1], %[c2] \n\t" /* c1 = c2 */
+ "movs %[c2], #0 \n\t" /* c2 = 0 */
+ "adds %[k], #4 \n\t" /* k += 4 */
+ "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
+ "ble 1b \n\t" /* if so, loop back, start with i = 0 */
+ "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
+ "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
+ /* end outer loop */
+
+ "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
+ RESUME_SYNTAX
+ : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
+ [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
+ : [result] "r" (result), [left] "r" (left), [right] "r" (right),
+ [last_word] "r" ((num_words - 1) * 4)
+ : "cc", "memory"
+ );
+
+#else /* Thumb-1 */
+ uint32_t r4, r5, r6, r7;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ "subs %[r3], #1 \n\t" /* r3 = num_words - 1 */
+ "lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */
+ "mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */
+ "lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */
+ "mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */
+ "movs %[r3], #0 \n\t" /* c0 = 0 */
+ "movs %[r4], #0 \n\t" /* c1 = 0 */
+ "movs %[r5], #0 \n\t" /* c2 = 0 */
+ "movs %[r6], #0 \n\t" /* k = 0 */
+
+ "push {%[r0]} \n\t" /* keep result on the stack */
+
+ "1: \n\t" /* outer loop (k < num_words) */
+ "movs %[r7], #0 \n\t" /* r7 = i = 0 */
+ "b 3f \n\t"
+
+ "2: \n\t" /* outer loop (k >= num_words) */
+ "movs %[r7], %[r6] \n\t" /* r7 = k */
+ "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
+ "subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */
+
+ "3: \n\t" /* inner loop */
+ "mov r10, %[r3] \n\t"
+ "mov r11, %[r4] \n\t"
+ "mov r12, %[r5] \n\t"
+ "mov r14, %[r6] \n\t"
+ "subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */
+
+ "ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */
+ "ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */
+
+ "lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */
+ "uxth %[r0], %[r0] \n\t" /* r0 = a0 */
+
+ "lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */
+ "uxth %[r4], %[r4] \n\t" /* r4 = b0 */
+
+ "movs %[r6], %[r3] \n\t" /* r6 = a1 */
+ "muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */
+ "muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */
+ "muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */
+ "muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */
+
+ /* Add middle terms */
+ "lsls %[r4], %[r3], #16 \n\t"
+ "lsrs %[r3], %[r3], #16 \n\t"
+ "adds %[r0], %[r4] \n\t"
+ "adcs %[r6], %[r3] \n\t"
+
+ "lsls %[r4], %[r5], #16 \n\t"
+ "lsrs %[r5], %[r5], #16 \n\t"
+ "adds %[r0], %[r4] \n\t"
+ "adcs %[r6], %[r5] \n\t"
+
+ "mov %[r3], r10\n\t"
+ "mov %[r4], r11\n\t"
+ "mov %[r5], r12\n\t"
+ "adds %[r3], %[r0] \n\t" /* add low word to c0 */
+ "adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */
+ "movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */
+ "adcs %[r5], %[r0] \n\t" /* add carry to c2 */
+
+ "mov %[r6], r14\n\t" /* r6 = k */
+
+ "adds %[r7], #4 \n\t" /* i += 4 */
+ "cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */
+ "bgt 4f \n\t" /* if so, exit the loop */
+ "cmp %[r7], %[r6] \n\t" /* i <= k? */
+ "ble 3b \n\t" /* if so, continue looping */
+
+ "4: \n\t" /* end inner loop */
+
+ "ldr %[r0], [sp, #0] \n\t" /* r0 = result */
+
+ "str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */
+ "mov %[r3], %[r4] \n\t" /* c0 = c1 */
+ "mov %[r4], %[r5] \n\t" /* c1 = c2 */
+ "movs %[r5], #0 \n\t" /* c2 = 0 */
+ "adds %[r6], #4 \n\t" /* k += 4 */
+ "cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
+ "ble 1b \n\t" /* if so, loop back, start with i = 0 */
+ "cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
+ "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
+ /* end outer loop */
+
+ "str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */
+ "pop {%[r0]} \n\t" /* pop result off the stack */
+
+ ".syntax divided \n\t"
+ : [r3] "+l" (num_words), [r4] "=&l" (r4),
+ [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
+ : [r0] "l" (result), [r1] "l" (left), [r2] "l" (right)
+ : "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+#endif
+}
+#define asm_mult 1
+#endif
+
+#if uECC_SQUARE_FUNC
+#if !asm_square
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+#if (uECC_PLATFORM != uECC_arm_thumb)
+ uint32_t c0 = 0;
+ uint32_t c1 = 0;
+ uint32_t c2 = 0;
+ uint32_t k = 0;
+ uint32_t i, tt;
+ uint32_t t0, t1;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+
+ "1: \n\t" /* outer loop (k < num_words) */
+ "movs %[i], #0 \n\t" /* i = 0 */
+ "b 3f \n\t"
+
+ "2: \n\t" /* outer loop (k >= num_words) */
+ "movs %[i], %[k] \n\t" /* i = k */
+ "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */
+
+ "3: \n\t" /* inner loop */
+ "subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
+
+ "ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */
+ "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */
+
+ "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */
+
+ "cmp %[i], %[tt] \n\t" /* (i < k - i) ? */
+ "bge 4f \n\t" /* if i >= k - i, skip */
+ "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
+ "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
+ "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
+
+ "4: \n\t"
+ "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */
+ "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */
+ "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */
+
+ "adds %[i], #4 \n\t" /* i += 4 */
+ "cmp %[i], %[k] \n\t" /* i >= k? */
+ "bge 5f \n\t" /* if so, exit the loop */
+ "subs %[tt], %[k], %[i] \n\t" /* tt = k - i */
+ "cmp %[i], %[tt] \n\t" /* i <= k - i? */
+ "ble 3b \n\t" /* if so, continue looping */
+
+ "5: \n\t" /* end inner loop */
+
+ "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */
+ "mov %[c0], %[c1] \n\t" /* c0 = c1 */
+ "mov %[c1], %[c2] \n\t" /* c1 = c2 */
+ "movs %[c2], #0 \n\t" /* c2 = 0 */
+ "adds %[k], #4 \n\t" /* k += 4 */
+ "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
+ "ble 1b \n\t" /* if so, loop back, start with i = 0 */
+ "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
+ "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */
+ /* end outer loop */
+
+ "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
+ RESUME_SYNTAX
+ : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
+ [k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
+ : [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4)
+ : "cc", "memory"
+ );
+
+#else
+ uint32_t r3, r4, r5, r6, r7;
+
+ __asm__ volatile (
+ ".syntax unified \n\t"
+ "subs %[r2], #1 \n\t" /* r2 = num_words - 1 */
+ "lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */
+ "mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */
+ "lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */
+ "mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */
+ "movs %[r2], #0 \n\t" /* c0 = 0 */
+ "movs %[r3], #0 \n\t" /* c1 = 0 */
+ "movs %[r4], #0 \n\t" /* c2 = 0 */
+ "movs %[r5], #0 \n\t" /* k = 0 */
+
+ "push {%[r0]} \n\t" /* keep result on the stack */
+
+ "1: \n\t" /* outer loop (k < num_words) */
+ "movs %[r6], #0 \n\t" /* r6 = i = 0 */
+ "b 3f \n\t"
+
+ "2: \n\t" /* outer loop (k >= num_words) */
+ "movs %[r6], %[r5] \n\t" /* r6 = k */
+ "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */
+ "subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */
+
+ "3: \n\t" /* inner loop */
+ "mov r10, %[r2] \n\t"
+ "mov r11, %[r3] \n\t"
+ "mov r12, %[r4] \n\t"
+ "mov r14, %[r5] \n\t"
+ "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
+
+ "ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */
+ "ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */
+
+ "lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */
+ "uxth %[r0], %[r0] \n\t" /* r0 = a0 */
+
+ "lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */
+ "uxth %[r3], %[r3] \n\t" /* r3 = b0 */
+
+ "movs %[r5], %[r2] \n\t" /* r5 = a1 */
+ "muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */
+ "muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */
+ "muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */
+ "muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */
+
+ /* Add middle terms */
+ "lsls %[r3], %[r2], #16 \n\t"
+ "lsrs %[r2], %[r2], #16 \n\t"
+ "adds %[r0], %[r3] \n\t"
+ "adcs %[r5], %[r2] \n\t"
+
+ "lsls %[r3], %[r4], #16 \n\t"
+ "lsrs %[r4], %[r4], #16 \n\t"
+ "adds %[r0], %[r3] \n\t"
+ "adcs %[r5], %[r4] \n\t"
+
+ /* Add to acc, doubling if necessary */
+ "mov %[r2], r10\n\t"
+ "mov %[r3], r11\n\t"
+ "mov %[r4], r12\n\t"
+
+ "cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */
+ "bge 4f \n\t" /* if i >= k - i, skip */
+ "movs %[r7], #0 \n\t" /* r7 = 0 */
+ "adds %[r2], %[r0] \n\t" /* add low word to c0 */
+ "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
+ "adcs %[r4], %[r7] \n\t" /* add carry to c2 */
+ "4: \n\t"
+ "movs %[r7], #0 \n\t" /* r7 = 0 */
+ "adds %[r2], %[r0] \n\t" /* add low word to c0 */
+ "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */
+ "adcs %[r4], %[r7] \n\t" /* add carry to c2 */
+
+ "mov %[r5], r14\n\t" /* r5 = k */
+
+ "adds %[r6], #4 \n\t" /* i += 4 */
+ "cmp %[r6], %[r5] \n\t" /* i >= k? */
+ "bge 5f \n\t" /* if so, exit the loop */
+ "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */
+ "cmp %[r6], %[r7] \n\t" /* i <= k - i? */
+ "ble 3b \n\t" /* if so, continue looping */
+
+ "5: \n\t" /* end inner loop */
+
+ "ldr %[r0], [sp, #0] \n\t" /* r0 = result */
+
+ "str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */
+ "mov %[r2], %[r3] \n\t" /* c0 = c1 */
+ "mov %[r3], %[r4] \n\t" /* c1 = c2 */
+ "movs %[r4], #0 \n\t" /* c2 = 0 */
+ "adds %[r5], #4 \n\t" /* k += 4 */
+ "cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */
+ "ble 1b \n\t" /* if so, loop back, start with i = 0 */
+ "cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
+ "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */
+ /* end outer loop */
+
+ "str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */
+ "pop {%[r0]} \n\t" /* pop result off the stack */
+
+ ".syntax divided \n\t"
+ : [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4),
+ [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7)
+ : [r0] "l" (result), [r1] "l" (left)
+ : "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
+ );
+#endif
+}
+#define asm_square 1
+#endif
+#endif /* uECC_SQUARE_FUNC */
+
+#endif /* _UECC_ASM_ARM_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc
new file mode 100644
index 00000000..8907fc18
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square.inc
@@ -0,0 +1,2311 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_ASM_ARM_MULT_SQUARE_H_
+#define _UECC_ASM_ARM_MULT_SQUARE_H_
+
+#define FAST_MULT_ASM_5 \
+ "push {r3} \n\t" \
+ "add r0, 12 \n\t" \
+ "add r2, 12 \n\t" \
+ "ldmia r1!, {r3,r4} \n\t" \
+ "ldmia r2!, {r6,r7} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adc r10, r10, r14 \n\t" \
+ "stmia r0!, {r9, r10} \n\t" \
+ \
+ "sub r0, 28 \n\t" \
+ "sub r2, 20 \n\t" \
+ "ldmia r2!, {r6,r7,r8} \n\t" \
+ "ldmia r1!, {r5} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r4, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "ldmia r1!, {r4} \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r5, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r4, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "ldr r9, [r0] \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, #0 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r5, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r3, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "ldr r10, [r0] \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r2!, {r7} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "umull r14, r9, r4, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adc r11, r11, r9 \n\t" \
+ "stmia r0!, {r10, r11} \n\t" \
+ "pop {r3} \n\t"
+
+#define FAST_MULT_ASM_5_TO_6 \
+ "cmp r3, #5 \n\t" \
+ "beq 1f \n\t" \
+ \
+ /* r4 = left high, r5 = right high */ \
+ "ldr r4, [r1] \n\t" \
+ "ldr r5, [r2] \n\t" \
+ \
+ "sub r0, #20 \n\t" \
+ "sub r1, #20 \n\t" \
+ "sub r2, #20 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r4, r8 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r10, r10, r6 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r14, r14, r6 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "str r14, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r10, r10, r6 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ /* skip past already-loaded (r4, r5) */ \
+ "ldr r7, [r1], #8 \n\t" \
+ "ldr r8, [r2], #8 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "umull r11, r12, r4, r5 \n\t" \
+ "adds r11, r11, r14 \n\t" \
+ "adc r12, r12, r9 \n\t" \
+ "stmia r0!, {r11, r12} \n\t"
+
+#define FAST_MULT_ASM_6 \
+ "push {r3} \n\t" \
+ "add r0, 12 \n\t" \
+ "add r2, 12 \n\t" \
+ "ldmia r1!, {r3,r4,r5} \n\t" \
+ "ldmia r2!, {r6,r7,r8} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r4, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "umull r9, r10, r5, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adc r12, r12, r10 \n\t" \
+ "stmia r0!, {r11, r12} \n\t" \
+ \
+ "sub r0, 36 \n\t" \
+ "sub r2, 24 \n\t" \
+ "ldmia r2!, {r6,r7,r8} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r4, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "ldmia r1!, {r4} \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r5, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r4, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "ldr r9, [r0] \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, #0 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "ldmia r1!, {r5} \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r3, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r5, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "ldr r10, [r0] \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r3, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "ldmia r2!, {r7} \n\t" \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "ldr r12, [r0] \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r2!, {r8} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r3, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r4, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r4, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r5, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "umull r10, r11, r5, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adc r14, r14, r11 \n\t" \
+ "stmia r0!, {r12, r14} \n\t" \
+ "pop {r3} \n\t"
+
+#define FAST_MULT_ASM_6_TO_7 \
+ "cmp r3, #6 \n\t" \
+ "beq 1f \n\t" \
+ \
+ /* r4 = left high, r5 = right high */ \
+ "ldr r4, [r1] \n\t" \
+ "ldr r5, [r2] \n\t" \
+ \
+ "sub r0, #24 \n\t" \
+ "sub r1, #24 \n\t" \
+ "sub r2, #24 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r4, r8 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r10, r10, r6 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r14, r14, r6 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "str r14, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r10, r10, r6 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r14, r14, r6 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ /* skip past already-loaded (r4, r5) */ \
+ "ldr r7, [r1], #8 \n\t" \
+ "ldr r8, [r2], #8 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "str r14, [r0], #4 \n\t" \
+ \
+ "umull r11, r12, r4, r5 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adc r12, r12, r10 \n\t" \
+ "stmia r0!, {r11, r12} \n\t"
+
+#define FAST_MULT_ASM_7 \
+ "push {r3} \n\t" \
+ "add r0, 24 \n\t" \
+ "add r2, 24 \n\t" \
+ "ldmia r1!, {r3} \n\t" \
+ "ldmia r2!, {r6} \n\t" \
+ \
+ "umull r9, r10, r3, r6 \n\t" \
+ "stmia r0!, {r9, r10} \n\t" \
+ \
+ "sub r0, 20 \n\t" \
+ "sub r2, 16 \n\t" \
+ "ldmia r2!, {r6, r7, r8} \n\t" \
+ "ldmia r1!, {r4, r5} \n\t" \
+ \
+ "umull r9, r10, r3, r6 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "mov r14, #0 \n\t" \
+ "umull r9, r12, r3, r7 \n\t" \
+ "adds r10, r10, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r9, r11, r4, r6 \n\t" \
+ "adds r10, r10, r9 \n\t" \
+ "adcs r12, r12, r11 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r3, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r5, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r4, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r3, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "ldr r12, [r0] \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r5, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "umull r9, r10, r3, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adc r12, r12, r10 \n\t" \
+ "stmia r0!, {r11, r12} \n\t" \
+ \
+ "sub r0, 44 \n\t" \
+ "sub r1, 16 \n\t" \
+ "sub r2, 28 \n\t" \
+ "ldmia r1!, {r3,r4,r5} \n\t" \
+ "ldmia r2!, {r6,r7,r8} \n\t" \
+ \
+ "umull r9, r10, r3, r6 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "mov r14, #0 \n\t" \
+ "umull r9, r12, r3, r7 \n\t" \
+ "adds r10, r10, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r9, r11, r4, r6 \n\t" \
+ "adds r10, r10, r9 \n\t" \
+ "adcs r12, r12, r11 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r3, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r5, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "ldmia r1!, {r4} \n\t" \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r5, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r3, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "ldr r12, [r0] \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r1!, {r5} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r3, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r4, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r4, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r5, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "ldr r9, [r0] \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, #0 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r4, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r5, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r3, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "ldr r10, [r0] \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r2!, {r7} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "ldmia r2!, {r8} \n\t" \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r4, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r3, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "ldr r12, [r0] \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r4, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r5, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "umull r10, r11, r3, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adc r14, r14, r11 \n\t" \
+ "stmia r0!, {r12, r14} \n\t" \
+ "pop {r3} \n\t"
+
+#define FAST_MULT_ASM_7_TO_8 \
+ "cmp r3, #7 \n\t" \
+ "beq 1f \n\t" \
+ \
+ /* r4 = left high, r5 = right high */ \
+ "ldr r4, [r1] \n\t" \
+ "ldr r5, [r2] \n\t" \
+ \
+ "sub r0, #28 \n\t" \
+ "sub r1, #28 \n\t" \
+ "sub r2, #28 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r4, r8 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r10, r10, r6 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r14, r14, r6 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "str r14, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r10, r10, r6 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r10, r10, r11 \n\t" \
+ "adcs r14, r14, r12 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r14, r14, r6 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "ldr r7, [r1], #4 \n\t" \
+ "ldr r8, [r2], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "str r14, [r0], #4 \n\t" \
+ \
+ "ldr r6, [r0] \n\t" \
+ "adds r9, r9, r6 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ /* skip past already-loaded (r4, r5) */ \
+ "ldr r7, [r1], #8 \n\t" \
+ "ldr r8, [r2], #8 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r9, r9, r11 \n\t" \
+ "adcs r10, r10, r12 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "umull r11, r12, r4, r5 \n\t" \
+ "adds r11, r11, r10 \n\t" \
+ "adc r12, r12, r14 \n\t" \
+ "stmia r0!, {r11, r12} \n\t"
+
+#define FAST_MULT_ASM_8 \
+ "push {r3} \n\t" \
+ "add r0, 24 \n\t" \
+ "add r2, 24 \n\t" \
+ "ldmia r1!, {r3,r4} \n\t" \
+ "ldmia r2!, {r6,r7} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adc r10, r10, r14 \n\t" \
+ "stmia r0!, {r9, r10} \n\t" \
+ \
+ "sub r0, 28 \n\t" \
+ "sub r2, 20 \n\t" \
+ "ldmia r2!, {r6,r7,r8} \n\t" \
+ "ldmia r1!, {r5} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r4, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "ldmia r1!, {r4} \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r5, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r4, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "ldr r9, [r0] \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, #0 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r5, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r3, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "ldr r10, [r0] \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r2!, {r7} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "umull r14, r9, r4, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adc r11, r11, r9 \n\t" \
+ "stmia r0!, {r10, r11} \n\t" \
+ \
+ "sub r0, 52 \n\t" \
+ "sub r1, 20 \n\t" \
+ "sub r2, 32 \n\t" \
+ "ldmia r1!, {r3,r4,r5} \n\t" \
+ "ldmia r2!, {r6,r7,r8} \n\t" \
+ \
+ "umull r11, r12, r3, r6 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r9, r3, r7 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r11, r14, r4, r6 \n\t" \
+ "adds r12, r12, r11 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r3, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r5, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r4, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r5, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "ldmia r1!, {r4} \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r5, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r4, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "ldr r9, [r0] \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, #0 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "ldmia r1!, {r5} \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r3, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r5, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "ldr r10, [r0] \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r4, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r5, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "ldmia r1!, {r4} \n\t" \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r5, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r3, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "ldr r12, [r0] \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r5, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r3, r8 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r4, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "ldmia r2!, {r7} \n\t" \
+ "mov r14, #0 \n\t" \
+ "umull r9, r10, r5, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r3, r6 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "umull r9, r10, r4, r8 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "ldr r9, [r0] \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adcs r12, r12, #0 \n\t" \
+ "adc r14, r14, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "ldmia r2!, {r8} \n\t" \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r5, r8 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r3, r7 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "umull r10, r11, r4, r6 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "ldr r10, [r0] \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r14, r14, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "ldmia r2!, {r6} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r5, r6 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r8 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r4, r7 \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "ldr r11, [r0] \n\t" \
+ "adds r14, r14, r11 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r14} \n\t" \
+ \
+ "ldmia r2!, {r7} \n\t" \
+ "mov r11, #0 \n\t" \
+ "umull r12, r14, r5, r7 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r3, r6 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "umull r12, r14, r4, r8 \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, r14 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "ldr r12, [r0] \n\t" \
+ "adds r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r9} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r14, r9, r3, r7 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r14, r9, r4, r6 \n\t" \
+ "adds r10, r10, r14 \n\t" \
+ "adcs r11, r11, r9 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r10} \n\t" \
+ \
+ "umull r9, r10, r4, r7 \n\t" \
+ "adds r11, r11, r9 \n\t" \
+ "adc r12, r12, r10 \n\t" \
+ "stmia r0!, {r11, r12} \n\t" \
+ "pop {r3} \n\t"
+
+#define FAST_SQUARE_ASM_5 \
+ "push {r2} \n\t" \
+ "ldmia r1!, {r2,r3,r4,r5,r6} \n\t" \
+ "push {r1} \n\t" \
+ \
+ "umull r11, r12, r2, r2 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r2, r3 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r11, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r8, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r2, r4 \n\t" \
+ "adds r11, r11, r11 \n\t" \
+ "adcs r12, r12, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r3 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r5 \n\t" \
+ "umull r1, r14, r3, r4 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r14 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r2, r6 \n\t" \
+ "umull r1, r14, r3, r5 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "umull r1, r14, r4, r4 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r3, r6 \n\t" \
+ "umull r1, r14, r4, r5 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r14 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r8, #0 \n\t" \
+ "umull r1, r10, r4, r6 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "umull r1, r10, r5, r5 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r1, r10, r5, r6 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "adds r12, r12, r1 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "umull r1, r10, r6, r6 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "stmia r0!, {r8, r11} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#define FAST_SQUARE_ASM_5_TO_6 \
+ "cmp r2, #5 \n\t" \
+ "beq 1f \n\t" \
+ \
+ "sub r0, #20 \n\t" \
+ "sub r1, #20 \n\t" \
+ \
+ /* Do off-center multiplication */ \
+ "ldmia r1!, {r6,r7,r8,r9,r10,r11} \n\t" \
+ "umull r3, r4, r6, r11 \n\t" \
+ "umull r6, r5, r7, r11 \n\t" \
+ "adds r4, r4, r6 \n\t" \
+ "umull r7, r6, r8, r11 \n\t" \
+ "adcs r5, r5, r7 \n\t" \
+ "umull r8, r7, r9, r11 \n\t" \
+ "adcs r6, r6, r8 \n\t" \
+ "umull r9, r8, r10, r11 \n\t" \
+ "adcs r7, r7, r9 \n\t" \
+ "adcs r8, r8, #0 \n\t" \
+ \
+ /* Multiply by 2 */ \
+ "mov r9, #0 \n\t" \
+ "adds r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r8, r8, r8 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ \
+ /* Add into previous */ \
+ "ldr r14, [r0], #4 \n\t" \
+ "adds r3, r3, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r4, r4, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r5, r5, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r6, r6, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r7, r7, r14 \n\t" \
+ "adcs r8, r8, #0 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "sub r0, #20 \n\t" \
+ \
+ /* Perform center multiplication */ \
+ "umlal r8, r9, r11, r11 \n\t" \
+ "stmia r0!, {r3,r4,r5,r6,r7,r8,r9} \n\t"
+
+#define FAST_SQUARE_ASM_6 \
+ "push {r2} \n\t" \
+ "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t" \
+ "push {r1} \n\t" \
+ \
+ "umull r11, r12, r2, r2 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r2, r3 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r11, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r8, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r2, r4 \n\t" \
+ "adds r11, r11, r11 \n\t" \
+ "adcs r12, r12, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r3 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r5 \n\t" \
+ "umull r1, r14, r3, r4 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r14 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r2, r6 \n\t" \
+ "umull r1, r14, r3, r5 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "umull r1, r14, r4, r4 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r7 \n\t" \
+ "umull r1, r14, r3, r6 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r14 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "umull r1, r14, r4, r5 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r14 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r3, r7 \n\t" \
+ "umull r1, r14, r4, r6 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "umull r1, r14, r5, r5 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r9, r9, r14 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r4, r7 \n\t" \
+ "umull r1, r14, r5, r6 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r14 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r8, #0 \n\t" \
+ "umull r1, r10, r5, r7 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "umull r1, r10, r6, r6 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r1, r10, r6, r7 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "adds r12, r12, r1 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "umull r1, r10, r7, r7 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "stmia r0!, {r8, r11} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#define FAST_SQUARE_ASM_6_TO_7 \
+ "cmp r2, #6 \n\t" \
+ "beq 1f \n\t" \
+ \
+ "sub r0, #24 \n\t" \
+ "sub r1, #24 \n\t" \
+ \
+ /* Do off-center multiplication */ \
+ "ldmia r1!, {r6,r7,r8,r9,r10,r11,r12} \n\t" \
+ "umull r3, r4, r6, r12 \n\t" \
+ "umull r6, r5, r7, r12 \n\t" \
+ "adds r4, r4, r6 \n\t" \
+ "umull r7, r6, r8, r12 \n\t" \
+ "adcs r5, r5, r7 \n\t" \
+ "umull r8, r7, r9, r12 \n\t" \
+ "adcs r6, r6, r8 \n\t" \
+ "umull r9, r8, r10, r12 \n\t" \
+ "adcs r7, r7, r9 \n\t" \
+ "umull r10, r9, r11, r12 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ \
+ /* Multiply by 2 */ \
+ "mov r10, #0 \n\t" \
+ "adds r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ \
+ /* Add into previous */ \
+ "ldr r14, [r0], #4 \n\t" \
+ "adds r3, r3, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r4, r4, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r5, r5, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r6, r6, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r7, r7, r14 \n\t" \
+ "ldr r14, [r0], #4 \n\t" \
+ "adcs r8, r8, r14 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "sub r0, #24 \n\t" \
+ \
+ /* Perform center multiplication */ \
+ "umlal r9, r10, r12, r12 \n\t" \
+ "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10} \n\t"
+
+#define FAST_SQUARE_ASM_7 \
+ "push {r2} \n\t" \
+ "ldmia r1!, {r2, r3, r4, r5, r6, r7, r8} \n\t" \
+ "push {r1} \n\t" \
+ "sub r1, 4 \n\t" \
+ \
+ "add r0, 24 \n\t" \
+ "umull r9, r10, r2, r8 \n\t" \
+ "stmia r0!, {r9, r10} \n\t" \
+ "sub r0, 32 \n\t" \
+ \
+ "umull r11, r12, r2, r2 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r2, r3 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r11, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r8, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r2, r4 \n\t" \
+ "adds r11, r11, r11 \n\t" \
+ "adcs r12, r12, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r3 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r5 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r3, r4 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r2, r6 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r3, r5 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r4, r4 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r7 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r3, r6 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r4, r5 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "ldmia r1!, {r2} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r3, r7 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r4, r6 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r5, r5 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r3, r2 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r4, r7 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r5, r6 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r4, r2 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r5, r7 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r6, r6 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r5, r2 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r6, r7 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r8, #0 \n\t" \
+ "umull r1, r10, r6, r2 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "umull r1, r10, r7, r7 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r1, r10, r7, r2 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "adds r12, r12, r1 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "umull r1, r10, r2, r2 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "stmia r0!, {r8, r11} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#define FAST_SQUARE_ASM_7_TO_8 \
+ "cmp r2, #7 \n\t" \
+ "beq 1f \n\t" \
+ \
+ "sub r0, #28 \n\t" \
+ "sub r1, #28 \n\t" \
+ \
+ /* Do off-center multiplication */ \
+ "ldmia r1!, {r6,r7,r8,r9,r10,r11,r12,r14} \n\t" \
+ "umull r3, r4, r6, r14 \n\t" \
+ "umull r6, r5, r7, r14 \n\t" \
+ "adds r4, r4, r6 \n\t" \
+ "umull r7, r6, r8, r14 \n\t" \
+ "adcs r5, r5, r7 \n\t" \
+ "umull r8, r7, r9, r14 \n\t" \
+ "adcs r6, r6, r8 \n\t" \
+ "umull r9, r8, r10, r14 \n\t" \
+ "adcs r7, r7, r9 \n\t" \
+ "umull r10, r9, r11, r14 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "umull r11, r10, r12, r14 \n\t" \
+ "adcs r9, r9, r11 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ \
+ /* Multiply by 2 */ \
+ "mov r11, #0 \n\t" \
+ "adds r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ \
+ /* Add into previous */ \
+ "ldr r12, [r0], #4 \n\t" \
+ "adds r3, r3, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r4, r4, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r5, r5, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r6, r6, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r7, r7, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r8, r8, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "sub r0, #28 \n\t" \
+ \
+ /* Perform center multiplication */ \
+ "umlal r10, r11, r14, r14 \n\t" \
+ "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} \n\t"
+
+#define FAST_SQUARE_ASM_8 \
+ "push {r2} \n\t" \
+ "ldmia r1!, {r2,r3,r4,r5,r6,r7,r8,r9} \n\t" \
+ "push {r1} \n\t" \
+ "sub r1, 8 \n\t" \
+ \
+ "add r0, 24 \n\t" \
+ "umull r10, r11, r2, r8 \n\t" \
+ "umull r12, r14, r2, r9 \n\t" \
+ "umull r8, r9, r3, r9 \n\t" \
+ "adds r11, r11, r12 \n\t" \
+ "adcs r12, r14, r8 \n\t" \
+ "adcs r14, r9, #0 \n\t" \
+ "stmia r0!, {r10, r11, r12, r14} \n\t" \
+ "sub r0, 40 \n\t" \
+ \
+ "umull r11, r12, r2, r2 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umull r10, r11, r2, r3 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r11, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "adds r12, r12, r10 \n\t" \
+ "adcs r8, r8, r11 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r11, r12, r2, r4 \n\t" \
+ "adds r11, r11, r11 \n\t" \
+ "adcs r12, r12, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "umull r11, r12, r3, r3 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r5 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r3, r4 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r2, r6 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r3, r5 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r4, r4 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r2, r7 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r3, r6 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r4, r5 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "ldmia r1!, {r2} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r3, r7 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r4, r6 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r5, r5 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r3, r2 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r4, r7 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r5, r6 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "ldmia r1!, {r3} \n\t" \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r4, r2 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r5, r7 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r6, r6 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r4, r3 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r5, r2 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r6, r7 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "ldr r14, [r0] \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umull r8, r9, r5, r3 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r6, r2 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adc r10, r10, r10 \n\t" \
+ "mov r14, r9 \n\t" \
+ "umlal r8, r9, r7, r7 \n\t" \
+ "cmp r14, r9 \n\t" \
+ "it hi \n\t" \
+ "adchi r10, r10, #0 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umull r8, r11, r6, r3 \n\t" \
+ "mov r14, r11 \n\t" \
+ "umlal r8, r11, r7, r2 \n\t" \
+ "cmp r14, r11 \n\t" \
+ "it hi \n\t" \
+ "adchi r12, r12, #0 \n\t" \
+ "adds r8, r8, r8 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adc r12, r12, r12 \n\t" \
+ "adds r8, r8, r9 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "adc r12, r12, #0 \n\t" \
+ "stmia r0!, {r8} \n\t" \
+ \
+ "mov r8, #0 \n\t" \
+ "umull r1, r10, r7, r3 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "umull r1, r10, r2, r2 \n\t" \
+ "adds r11, r11, r1 \n\t" \
+ "adcs r12, r12, r10 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "stmia r0!, {r11} \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umull r1, r10, r2, r3 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "adds r12, r12, r1 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "adc r11, r11, #0 \n\t" \
+ "stmia r0!, {r12} \n\t" \
+ \
+ "umull r1, r10, r3, r3 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "adcs r11, r11, r10 \n\t" \
+ "stmia r0!, {r8, r11} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc
new file mode 100644
index 00000000..c554d20e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_arm_mult_square_umaal.inc
@@ -0,0 +1,1202 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_ASM_ARM_MULT_SQUARE_H_
+#define _UECC_ASM_ARM_MULT_SQUARE_H_
+
+#define FAST_MULT_ASM_5 \
+ "push {r3} \n\t" \
+ "ldmia r2!, {r3, r4, r5, r6, r7} \n\t" \
+ "push {r2} \n\t" \
+ \
+ "ldr r2, [r1], #4 \n\t" \
+ "umull r8, r9, r3, r2 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r4, r2 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r5, r2 \n\t" \
+ "mov r12, #0 \n\t" \
+ "umaal r11, r12, r6, r2 \n\t" \
+ "mov r14, #0 \n\t" \
+ "umaal r12, r14, r7, r2 \n\t" \
+ \
+ "ldr r2, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r3, r2 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r2 \n\t" \
+ "umaal r10, r11, r5, r2 \n\t" \
+ "umaal r11, r12, r6, r2 \n\t" \
+ "umaal r12, r14, r7, r2 \n\t" \
+ \
+ "ldr r2, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r3, r2 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r2 \n\t" \
+ "umaal r10, r11, r5, r2 \n\t" \
+ "umaal r11, r12, r6, r2 \n\t" \
+ "umaal r12, r14, r7, r2 \n\t" \
+ \
+ "ldr r2, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r3, r2 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r2 \n\t" \
+ "umaal r10, r11, r5, r2 \n\t" \
+ "umaal r11, r12, r6, r2 \n\t" \
+ "umaal r12, r14, r7, r2 \n\t" \
+ \
+ "ldr r2, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r3, r2 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r2 \n\t" \
+ "umaal r10, r11, r5, r2 \n\t" \
+ "umaal r11, r12, r6, r2 \n\t" \
+ "umaal r12, r14, r7, r2 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t" \
+ "str r12, [r0], #4 \n\t" \
+ "str r14, [r0], #4 \n\t" \
+ \
+ "pop {r2, r3} \n\t"
+
+#define FAST_MULT_ASM_5_TO_6 \
+ "cmp r3, #5 \n\t" \
+ "beq 1f \n\t" \
+ \
+ /* r4 = left high */ \
+ "ldr r4, [r1] \n\t" \
+ \
+ "sub r0, #20 \n\t" \
+ "sub r1, #20 \n\t" \
+ "sub r2, #20 \n\t" \
+ \
+ /* Do right side */ \
+ "ldr r14, [r2], #4 \n\t" \
+ "mov r5, #0 \n\t" \
+ "ldr r6, [r0], #4 \n\t" \
+ "umaal r5, r6, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r7, [r0], #4 \n\t" \
+ "umaal r6, r7, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r8, [r0], #4 \n\t" \
+ "umaal r7, r8, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r9, [r0], #4 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r10, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r14 \n\t" \
+ "sub r0, #20 \n\t" \
+ \
+ /* r4 = right high */ \
+ "ldr r4, [r2], #4 \n\t" \
+ \
+ /* Do left side */ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r12, #0 \n\t" \
+ "umaal r12, r5, r4, r14 \n\t" \
+ "str r12, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r5, r6, r4, r14 \n\t" \
+ "str r5, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r6, r7, r4, r14 \n\t" \
+ "str r6, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r7, r8, r4, r14 \n\t" \
+ "str r7, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r9, r10, r4, r14 \n\t" \
+ "stmia r0!, {r9, r10} \n\t"
+
+#define FAST_MULT_ASM_6 \
+ "ldmia r2!, {r4, r5, r6} \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "umull r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t" \
+ \
+ "sub r0, #24 \n\t" \
+ "sub r1, #24 \n\t" \
+ "ldmia r2!, {r4, r5, r6} \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "mov r9, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t"
+
+#define FAST_MULT_ASM_6_TO_7 \
+ "cmp r3, #6 \n\t" \
+ "beq 1f \n\t" \
+ \
+ /* r4 = left high */ \
+ "ldr r4, [r1] \n\t" \
+ \
+ "sub r0, #24 \n\t" \
+ "sub r1, #24 \n\t" \
+ "sub r2, #24 \n\t" \
+ \
+ /* Do right side */ \
+ "ldr r14, [r2], #4 \n\t" \
+ "mov r5, #0 \n\t" \
+ "ldr r6, [r0], #4 \n\t" \
+ "umaal r5, r6, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r7, [r0], #4 \n\t" \
+ "umaal r6, r7, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r8, [r0], #4 \n\t" \
+ "umaal r7, r8, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r9, [r0], #4 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r10, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r11, [r0], #4 \n\t" \
+ "umaal r10, r11, r4, r14 \n\t" \
+ "sub r0, #24 \n\t" \
+ \
+ /* r4 = right high */ \
+ "ldr r4, [r2], #4 \n\t" \
+ \
+ /* Do left side */ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r12, #0 \n\t" \
+ "umaal r12, r5, r4, r14 \n\t" \
+ "str r12, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r5, r6, r4, r14 \n\t" \
+ "str r5, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r6, r7, r4, r14 \n\t" \
+ "str r6, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r7, r8, r4, r14 \n\t" \
+ "str r7, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r9, r10, r4, r14 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r10, r11, r4, r14 \n\t" \
+ "stmia r0!, {r10, r11} \n\t"
+
+#define FAST_MULT_ASM_7 \
+ "ldmia r2!, {r4, r5, r6, r7} \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "umull r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "mov r12, #0 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t" \
+ "str r12, [r0], #4 \n\t" \
+ \
+ "sub r0, #28 \n\t" \
+ "sub r1, #28 \n\t" \
+ "ldmia r2!, {r4, r5, r6} \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "mov r9, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t"
+
+#define FAST_MULT_ASM_7_TO_8 \
+ "cmp r3, #7 \n\t" \
+ "beq 1f \n\t" \
+ "push {r3} \n\t" \
+ \
+ /* r4 = left high */ \
+ "ldr r4, [r1] \n\t" \
+ \
+ "sub r0, #28 \n\t" \
+ "sub r1, #28 \n\t" \
+ "sub r2, #28 \n\t" \
+ \
+ /* Do right side */ \
+ "ldr r14, [r2], #4 \n\t" \
+ "mov r5, #0 \n\t" \
+ "ldr r6, [r0], #4 \n\t" \
+ "umaal r5, r6, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r7, [r0], #4 \n\t" \
+ "umaal r6, r7, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r8, [r0], #4 \n\t" \
+ "umaal r7, r8, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r9, [r0], #4 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r10, [r0], #4 \n\t" \
+ "umaal r9, r10, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r11, [r0], #4 \n\t" \
+ "umaal r10, r11, r4, r14 \n\t" \
+ "ldr r14, [r2], #4 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "umaal r11, r12, r4, r14 \n\t" \
+ "sub r0, #28 \n\t" \
+ \
+ /* r4 = right high */ \
+ "ldr r4, [r2], #4 \n\t" \
+ \
+ /* Do left side */ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r3, #0 \n\t" \
+ "umaal r3, r5, r4, r14 \n\t" \
+ "str r3, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r5, r6, r4, r14 \n\t" \
+ "str r5, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r6, r7, r4, r14 \n\t" \
+ "str r6, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r7, r8, r4, r14 \n\t" \
+ "str r7, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r9, r10, r4, r14 \n\t" \
+ "str r9, [r0], #4 \n\t" \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r10, r11, r4, r14 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "umaal r11, r12, r4, r14 \n\t" \
+ "stmia r0!, {r11, r12} \n\t" \
+ "pop {r3} \n\t"
+
+#define FAST_MULT_ASM_8 \
+ "ldmia r2!, {r4, r5, r6, r7} \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "umull r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "mov r12, #0 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t" \
+ "str r12, [r0], #4 \n\t" \
+ \
+ "sub r0, #32 \n\t" \
+ "sub r1, #32 \n\t" \
+ "ldmia r2!, {r4, r5, r6, r7} \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "mov r9, #0 \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "mov r11, #0 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "mov r12, #0 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "ldr r14, [r1], #4 \n\t" \
+ "ldr r8, [r0] \n\t" \
+ "umaal r8, r9, r4, r14 \n\t" \
+ "str r8, [r0], #4 \n\t" \
+ "umaal r9, r10, r5, r14 \n\t" \
+ "umaal r10, r11, r6, r14 \n\t" \
+ "umaal r11, r12, r7, r14 \n\t" \
+ \
+ "str r9, [r0], #4 \n\t" \
+ "str r10, [r0], #4 \n\t" \
+ "str r11, [r0], #4 \n\t" \
+ "str r12, [r0], #4 \n\t"
+
+#define FAST_SQUARE_ASM_5 \
+ "ldmia r1!, {r9,r10,r11,r12,r14} \n\t" \
+ "push {r1, r2} \n\t" \
+ \
+ "umull r1, r2, r10, r9 \n\t" \
+ "mov r3, #0 \n\t" \
+ "umaal r2, r3, r11, r9 \n\t" \
+ "mov r4, #0 \n\t" \
+ "umaal r3, r4, r12, r9 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r14, r9 \n\t" \
+ \
+ "mov r6, #0 \n\t" \
+ "umaal r6, r3, r11, r10 \n\t" \
+ "umaal r3, r4, r12, r10 \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r2, r2, r2 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r3, r3, r3 \n\t" \
+ \
+ "umull r7, r8, r9, r9 \n\t" \
+ /* Store carry in r9 */ \
+ "mov r9, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ "adds r8, r8, r1 \n\t" \
+ "stmia r0!, {r7,r8} \n\t" \
+ \
+ "umull r7, r8, r10, r10 \n\t" \
+ "adcs r7, r7, r2 \n\t" \
+ "adcs r8, r8, r6 \n\t" \
+ "stmia r0!, {r7,r8} \n\t" \
+ \
+ "umaal r4, r5, r14, r10 \n\t" \
+ /* Store carry in r10 */ \
+ "mov r10, #0 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ \
+ "mov r1, #0 \n\t" \
+ "umaal r1, r4, r12, r11 \n\t" \
+ "umaal r4, r5, r14, r11 \n\t" \
+ \
+ "mov r2, #0 \n\t" \
+ "umaal r2, r5, r14, r12 \n\t" \
+ /* Load carry from r9 */ \
+ "lsrs r9, #1 \n\t" \
+ "adcs r1, r1, r1 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r2, r2, r2 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ /* r9 is 0 now */ \
+ "adc r9, r9, #0 \n\t" \
+ \
+ /* Use carry from r10 */ \
+ "umaal r3, r10, r11, r11 \n\t" \
+ "adds r10, r10, r1 \n\t" \
+ "stmia r0!, {r3,r10} \n\t" \
+ \
+ "umull r6, r10, r12, r12 \n\t" \
+ "adcs r6, r6, r4 \n\t" \
+ "adcs r10, r10, r2 \n\t" \
+ "stmia r0!, {r6,r10} \n\t" \
+ \
+ "umull r6, r10, r14, r14 \n\t" \
+ "adcs r6, r6, r5 \n\t" \
+ "adcs r10, r10, r9 \n\t" \
+ "stmia r0!, {r6,r10} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#define FAST_SQUARE_ASM_5_TO_6 \
+ "cmp r2, #5 \n\t" \
+ "beq 1f \n\t" \
+ \
+ "sub r0, #20 \n\t" \
+ "sub r1, #20 \n\t" \
+ \
+ /* Do off-center multiplication */ \
+ "ldmia r1!, {r5,r6,r7,r8,r9,r14} \n\t" \
+ "umull r3, r4, r5, r14 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r6, r14 \n\t" \
+ "mov r6, #0 \n\t" \
+ "umaal r5, r6, r7, r14 \n\t" \
+ "mov r7, #0 \n\t" \
+ "umaal r6, r7, r8, r14 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r7, r8, r9, r14 \n\t" \
+ \
+ /* Multiply by 2 */ \
+ "mov r9, #0 \n\t" \
+ "adds r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r8, r8, r8 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ \
+ /* Add into previous */ \
+ "ldr r12, [r0], #4 \n\t" \
+ "adds r3, r3, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r4, r4, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r5, r5, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r6, r6, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r7, r7, r12 \n\t" \
+ "adcs r8, r8, #0 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "sub r0, #20 \n\t" \
+ \
+ /* Perform center multiplication */ \
+ "umlal r8, r9, r14, r14 \n\t" \
+ "stmia r0!, {r3,r4,r5,r6,r7,r8,r9} \n\t"
+
+#define FAST_SQUARE_ASM_6 \
+ "ldmia r1!, {r8,r9,r10,r11,r12,r14} \n\t" \
+ "push {r1, r2} \n\t" \
+ \
+ "umull r1, r2, r9, r8 \n\t" \
+ "mov r3, #0 \n\t" \
+ "umaal r2, r3, r10, r8 \n\t" \
+ "mov r4, #0 \n\t" \
+ "umaal r3, r4, r11, r8 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r12, r8 \n\t" \
+ "mov r6, #0 \n\t" \
+ "umaal r5, r6, r14, r8 \n\t" \
+ \
+ "mov r7, #0 \n\t" \
+ "umaal r7, r3, r10, r9 \n\t" \
+ "umaal r3, r4, r11, r9 \n\t" \
+ "umaal r4, r5, r12, r9 \n\t" \
+ "push {r4, r5} \n\t" \
+ "adds r1, r1, r1 \n\t" \
+ "adcs r2, r2, r2 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r3, r3, r3 \n\t" \
+ \
+ "umull r4, r5, r8, r8 \n\t" \
+ /* Store carry in r8 */ \
+ "mov r8, #0 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ "adds r5, r5, r1 \n\t" \
+ "stmia r0!, {r4,r5} \n\t" \
+ \
+ "umull r4, r5, r9, r9 \n\t" \
+ "adcs r4, r4, r2 \n\t" \
+ "adcs r5, r5, r7 \n\t" \
+ "stmia r0!, {r4,r5} \n\t" \
+ \
+ "pop {r4, r5} \n\t" \
+ "umaal r5, r6, r14, r9 \n\t" \
+ /* Store carry in r9 */ \
+ "mov r9, #0 \n\t" \
+ "adc r9, r9, #0 \n\t" \
+ \
+ "mov r1, #0 \n\t" \
+ "umaal r1, r4, r11, r10 \n\t" \
+ "umaal r4, r5, r12, r10 \n\t" \
+ "umaal r5, r6, r14, r10 \n\t" \
+ \
+ "mov r2, #0 \n\t" \
+ "umaal r2, r5, r12, r11 \n\t" \
+ "umaal r5, r6, r14, r11 \n\t" \
+ \
+ "mov r7, #0 \n\t" \
+ "umaal r7, r6, r14, r12 \n\t" \
+ \
+ /* Load carry from r8 */ \
+ "lsrs r8, #1 \n\t" \
+ "adcs r1, r1, r1 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r2, r2, r2 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ \
+ /* Use carry from r9 */ \
+ "umaal r3, r9, r10, r10 \n\t" \
+ "adds r9, r9, r1 \n\t" \
+ "stmia r0!, {r3,r9} \n\t" \
+ \
+ "umull r9, r10, r11, r11 \n\t" \
+ "adcs r9, r9, r4 \n\t" \
+ "adcs r10, r10, r2 \n\t" \
+ "stmia r0!, {r9,r10} \n\t" \
+ \
+ "umull r9, r10, r12, r12 \n\t" \
+ "adcs r9, r9, r5 \n\t" \
+ "adcs r10, r10, r7 \n\t" \
+ "stmia r0!, {r9,r10} \n\t" \
+ \
+ "umull r9, r10, r14, r14 \n\t" \
+ "adcs r9, r9, r6 \n\t" \
+ "adcs r10, r10, r8 \n\t" \
+ "stmia r0!, {r9,r10} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#define FAST_SQUARE_ASM_6_TO_7 \
+ "cmp r2, #6 \n\t" \
+ "beq 1f \n\t" \
+ \
+ "sub r0, #24 \n\t" \
+ "sub r1, #24 \n\t" \
+ \
+ /* Do off-center multiplication */ \
+ "ldmia r1!, {r5,r6,r7,r8,r9,r10,r14} \n\t" \
+ "umull r3, r4, r5, r14 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r6, r14 \n\t" \
+ "mov r6, #0 \n\t" \
+ "umaal r5, r6, r7, r14 \n\t" \
+ "mov r7, #0 \n\t" \
+ "umaal r6, r7, r8, r14 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r7, r8, r9, r14 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umaal r8, r9, r10, r14 \n\t" \
+ \
+ /* Multiply by 2 */ \
+ "mov r10, #0 \n\t" \
+ "adds r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ \
+ /* Add into previous */ \
+ "ldr r12, [r0], #4 \n\t" \
+ "adds r3, r3, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r4, r4, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r5, r5, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r6, r6, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r7, r7, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r8, r8, r12 \n\t" \
+ "adcs r9, r9, #0 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "sub r0, #24 \n\t" \
+ \
+ /* Perform center multiplication */ \
+ "umlal r9, r10, r14, r14 \n\t" \
+ "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10} \n\t"
+
+#define FAST_SQUARE_ASM_7 \
+ "ldmia r1!, {r9,r10,r11,r12} \n\t" \
+ "push {r2} \n\t" \
+ \
+ "umull r14, r2, r10, r9 \n\t" \
+ "mov r3, #0 \n\t" \
+ "umaal r2, r3, r11, r9 \n\t" \
+ "mov r4, #0 \n\t" \
+ "umaal r3, r4, r12, r9 \n\t" \
+ \
+ "mov r5, #0 \n\t" \
+ "umaal r5, r3, r11, r10 \n\t" \
+ "adds r14, r14, r14 \n\t" \
+ "adcs r2, r2, r2 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ /* Store carry in r7 */ \
+ "mov r7, #0 \n\t" \
+ "adc r7, r7, #0 \n\t" \
+ \
+ "umull r6, r8, r9, r9 \n\t" \
+ "adds r8, r8, r14 \n\t" \
+ "stmia r0!, {r6,r8} \n\t" \
+ \
+ "umull r6, r8, r10, r10 \n\t" \
+ "adcs r6, r6, r2 \n\t" \
+ "adcs r8, r8, r5 \n\t" \
+ "stmia r0!, {r6,r8} \n\t" \
+ /* Store carry in r8 */ \
+ "mov r8, #0 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ \
+ "ldmia r1!, {r2, r6, r14} \n\t" \
+ "push {r1} \n\t" \
+ "umaal r3, r4, r2, r9 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r6, r9 \n\t" \
+ "mov r1, #0 \n\t" \
+ "umaal r5, r1, r14, r9 \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umaal r3, r9, r12, r10 \n\t" \
+ "umaal r9, r4, r2, r10 \n\t" \
+ "umaal r4, r5, r6, r10 \n\t" \
+ "umaal r5, r1, r14, r10 \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umaal r10, r9, r12, r11 \n\t" \
+ "umaal r9, r4, r2, r11 \n\t" \
+ "umaal r4, r5, r6, r11 \n\t" \
+ "umaal r5, r1, r14, r11 \n\t" \
+ \
+ /* Load carry from r7 */ \
+ "lsrs r7, #1 \n\t" \
+ "adcs r3, r3, r3 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ /* Store carry back in r7 */ \
+ "adc r7, r7, #0 \n\t" \
+ \
+ /* Use carry from r8 */ \
+ "umaal r3, r8, r11, r11 \n\t" \
+ "adds r8, r8, r10 \n\t" \
+ "stmia r0!, {r3,r8} \n\t" \
+ /* Store carry back in r8 */ \
+ "mov r8, #0 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ \
+ "mov r3, #0 \n\t" \
+ "umaal r3, r4, r2, r12 \n\t" \
+ "umaal r4, r5, r6, r12 \n\t" \
+ "umaal r5, r1, r14, r12 \n\t" \
+ \
+ "mov r10, #0 \n\t" \
+ "umaal r10, r5, r6, r2 \n\t" \
+ "umaal r5, r1, r14, r2 \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umaal r11, r1, r14, r6 \n\t" \
+ \
+ /* Load carry from r7 */ \
+ "lsrs r7, #1 \n\t" \
+ "adcs r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adcs r1, r1, r1 \n\t" \
+ "adc r7, r7, #0 \n\t" \
+ \
+ /* Use carry from r8 */ \
+ "umaal r8, r9, r12, r12 \n\t" \
+ "adds r9, r9, r3 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ \
+ "umull r8, r9, r2, r2 \n\t" \
+ "adcs r8, r8, r4 \n\t" \
+ "adcs r9, r9, r10 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ \
+ "umull r8, r9, r6, r6 \n\t" \
+ "adcs r8, r8, r5 \n\t" \
+ "adcs r9, r9, r11 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ \
+ "umull r8, r9, r14, r14 \n\t" \
+ "adcs r8, r8, r1 \n\t" \
+ "adcs r9, r9, r7 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ "pop {r1, r2} \n\t"
+
+#define FAST_SQUARE_ASM_7_TO_8 \
+ "cmp r2, #7 \n\t" \
+ "beq 1f \n\t" \
+ \
+ "sub r0, #28 \n\t" \
+ "sub r1, #28 \n\t" \
+ \
+ /* Do off-center multiplication */ \
+ "ldmia r1!, {r5,r6,r7,r8,r9,r10,r11,r14} \n\t" \
+ "umull r3, r4, r5, r14 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r6, r14 \n\t" \
+ "mov r6, #0 \n\t" \
+ "umaal r5, r6, r7, r14 \n\t" \
+ "mov r7, #0 \n\t" \
+ "umaal r6, r7, r8, r14 \n\t" \
+ "mov r8, #0 \n\t" \
+ "umaal r7, r8, r9, r14 \n\t" \
+ "mov r9, #0 \n\t" \
+ "umaal r8, r9, r10, r14 \n\t" \
+ "mov r10, #0 \n\t" \
+ "umaal r9, r10, r11, r14 \n\t" \
+ \
+ /* Multiply by 2 */ \
+ "mov r11, #0 \n\t" \
+ "adds r3, r3, r3 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adcs r8, r8, r8 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adcs r10, r10, r10 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ \
+ /* Add into previous */ \
+ "ldr r12, [r0], #4 \n\t" \
+ "adds r3, r3, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r4, r4, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r5, r5, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r6, r6, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r7, r7, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r8, r8, r12 \n\t" \
+ "ldr r12, [r0], #4 \n\t" \
+ "adcs r9, r9, r12 \n\t" \
+ "adcs r10, r10, #0 \n\t" \
+ "adcs r11, r11, #0 \n\t" \
+ "sub r0, #28 \n\t" \
+ \
+ /* Perform center multiplication */ \
+ "umlal r10, r11, r14, r14 \n\t" \
+ "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} \n\t"
+
+#define FAST_SQUARE_ASM_8 \
+ "ldmia r1!, {r10,r11,r12,r14} \n\t" \
+ "push {r2} \n\t" \
+ \
+ "umull r2, r3, r11, r10 \n\t" \
+ "mov r4, #0 \n\t" \
+ "umaal r3, r4, r12, r10 \n\t" \
+ "mov r5, #0 \n\t" \
+ "umaal r4, r5, r14, r10 \n\t" \
+ \
+ "mov r6, #0 \n\t" \
+ "umaal r6, r4, r12, r11 \n\t" \
+ "adds r2, r2, r2 \n\t" \
+ "adcs r3, r3, r3 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ /* Store carry in r7 */ \
+ "mov r7, #0 \n\t" \
+ "adc r7, r7, #0 \n\t" \
+ \
+ "umull r8, r9, r10, r10 \n\t" \
+ "adds r9, r9, r2 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ \
+ "umull r8, r9, r11, r11 \n\t" \
+ "adcs r8, r8, r3 \n\t" \
+ "adcs r9, r9, r6 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ /* Store carry in r8 */ \
+ "mov r8, #0 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ \
+ "ldmia r1!, {r2, r3} \n\t" \
+ "push {r1} \n\t" \
+ "umaal r4, r5, r2, r10 \n\t" \
+ "mov r6, #0 \n\t" \
+ "umaal r5, r6, r3, r10 \n\t" \
+ \
+ "mov r9, #0 \n\t" \
+ "umaal r9, r4, r14, r11 \n\t" \
+ "umaal r4, r5, r2, r11 \n\t" \
+ \
+ "mov r1, #0 \n\t" \
+ "umaal r1, r4, r14, r12 \n\t" \
+ \
+ /* Load carry from r7 */ \
+ "lsrs r7, #1 \n\t" \
+ "adcs r9, r9, r9 \n\t" \
+ "adcs r1, r1, r1 \n\t" \
+ /* Store carry back in r7 */ \
+ "adc r7, r7, #0 \n\t" \
+ \
+ /* Use carry from r8 */ \
+ "umaal r8, r9, r12, r12 \n\t" \
+ "adds r9, r9, r1 \n\t" \
+ "stmia r0!, {r8,r9} \n\t" \
+ /* Store carry back in r8 */ \
+ "mov r8, #0 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ \
+ "pop {r1} \n\t" \
+ /* TODO could fix up r1 value on stack here */ \
+ /* and leave the value on the stack (rather */ \
+ /* than popping) if supporting curves > 256 bits */ \
+ "ldr r9, [r1], #4 \n\t" \
+ "ldr r1, [r1] \n\t" \
+ \
+ "push {r7} \n\t" \
+ "umaal r5, r6, r9, r10 \n\t" \
+ "mov r7, #0 \n\t" \
+ "umaal r6, r7, r1, r10 \n\t" \
+ /* Carry now stored in r10 */ \
+ "pop {r10} \n\t" \
+ \
+ "umaal r4, r5, r3, r11 \n\t" \
+ "umaal r5, r6, r9, r11 \n\t" \
+ "umaal r6, r7, r1, r11 \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umaal r11, r4, r2, r12 \n\t" \
+ "umaal r4, r5, r3, r12 \n\t" \
+ "umaal r5, r6, r9, r12 \n\t" \
+ "umaal r6, r7, r1, r12 \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umaal r12, r4, r2, r14 \n\t" \
+ "umaal r4, r5, r3, r14 \n\t" \
+ "umaal r5, r6, r9, r14 \n\t" \
+ "umaal r6, r7, r1, r14 \n\t" \
+ \
+ /* Load carry from r10 */ \
+ "lsrs r10, #1 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adcs r12, r12, r12 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ \
+ /* Use carry from r8 */ \
+ "umaal r8, r11, r14, r14 \n\t" \
+ "adds r11, r11, r12 \n\t" \
+ "stmia r0!, {r8,r11} \n\t" \
+ /* Store carry back in r8 */ \
+ "mov r8, #0 \n\t" \
+ "adc r8, r8, #0 \n\t" \
+ \
+ "mov r11, #0 \n\t" \
+ "umaal r11, r5, r3, r2 \n\t" \
+ "umaal r5, r6, r9, r2 \n\t" \
+ "umaal r6, r7, r1, r2 \n\t" \
+ \
+ "mov r12, #0 \n\t" \
+ "umaal r12, r6, r9, r3 \n\t" \
+ "umaal r6, r7, r1, r3 \n\t" \
+ \
+ "mov r14, #0 \n\t" \
+ "umaal r14, r7, r1, r9 \n\t" \
+ \
+ /* Load carry from r10 */ \
+ "lsrs r10, #1 \n\t" \
+ "adcs r4, r4, r4 \n\t" \
+ "adcs r11, r11, r11 \n\t" \
+ "adcs r5, r5, r5 \n\t" \
+ "adcs r12, r12, r12 \n\t" \
+ "adcs r6, r6, r6 \n\t" \
+ "adcs r14, r14, r14 \n\t" \
+ "adcs r7, r7, r7 \n\t" \
+ "adc r10, r10, #0 \n\t" \
+ \
+ /* Use carry from r8 */ \
+ "umaal r4, r8, r2, r2 \n\t" \
+ "adds r8, r8, r11 \n\t" \
+ "stmia r0!, {r4,r8} \n\t" \
+ \
+ "umull r4, r8, r3, r3 \n\t" \
+ "adcs r4, r4, r5 \n\t" \
+ "adcs r8, r8, r12 \n\t" \
+ "stmia r0!, {r4,r8} \n\t" \
+ \
+ "umull r4, r8, r9, r9 \n\t" \
+ "adcs r4, r4, r6 \n\t" \
+ "adcs r8, r8, r14 \n\t" \
+ "stmia r0!, {r4,r8} \n\t" \
+ \
+ "umull r4, r8, r1, r1 \n\t" \
+ "adcs r4, r4, r7 \n\t" \
+ "adcs r8, r8, r10 \n\t" \
+ "stmia r0!, {r4,r8} \n\t" \
+ /* TODO pop {r1, r2} if supporting curves > 256 bits */ \
+ "pop {r2} \n\t"
+
+#endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr.inc
new file mode 100644
index 00000000..c9880403
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr.inc
@@ -0,0 +1,1089 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_ASM_AVR_H_
+#define _UECC_ASM_AVR_H_
+
+#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ #define uECC_MIN_WORDS 32
+#endif
+#if uECC_SUPPORTS_secp224r1
+ #undef uECC_MIN_WORDS
+ #define uECC_MIN_WORDS 28
+#endif
+#if uECC_SUPPORTS_secp192r1
+ #undef uECC_MIN_WORDS
+ #define uECC_MIN_WORDS 24
+#endif
+#if uECC_SUPPORTS_secp160r1
+ #undef uECC_MIN_WORDS
+ #define uECC_MIN_WORDS 20
+#endif
+
+#if __AVR_HAVE_EIJMP_EICALL__
+ #define IJMP "eijmp \n\t"
+#else
+ #define IJMP "ijmp \n\t"
+#endif
+
+#if (uECC_OPTIMIZATION_LEVEL >= 2)
+
+uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
+ volatile uECC_word_t *v = vli;
+ __asm__ volatile (
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "ldi r30, pm_lo8(1f) \n\t"
+ "ldi r31, pm_hi8(1f) \n\t"
+ "sub r30, %[num] \n\t"
+ "sbc r31, __zero_reg__ \n\t"
+ IJMP
+ #endif
+
+ REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t")
+ "1: \n\t"
+ : "+x" (v)
+ : [num] "r" (num_words)
+ :
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "r30", "r31", "cc"
+ #endif
+ );
+}
+#define asm_clear 1
+
+uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) {
+ volatile uECC_word_t *d = dest;
+ __asm__ volatile (
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "ldi r30, pm_lo8(1f) \n\t"
+ "ldi r31, pm_hi8(1f) \n\t"
+ "sub r30, %[num] \n\t"
+ "sbc r31, __zero_reg__ \n\t"
+ IJMP
+ #endif
+
+ REPEAT(uECC_MAX_WORDS,
+ "ld r0, y+ \n\t"
+ "st x+, r0 \n\t")
+ "1: \n\t"
+ : "+x" (d), "+y" (src)
+ : [num] "r" ((uint8_t)(num_words * 2))
+ : "r0",
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "r30", "r31", "cc"
+ #endif
+ );
+}
+#define asm_set 1
+
+uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) {
+ volatile uECC_word_t *v = vli;
+ __asm__ volatile (
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "ldi r30, pm_lo8(1f) \n\t"
+ "ldi r31, pm_hi8(1f) \n\t"
+ "sub r30, %[jump] \n\t"
+ "sbc r31, __zero_reg__ \n\t"
+ #endif
+
+ "add r26, %[num] \n\t"
+ "adc r27, __zero_reg__ \n\t"
+ "ld r0, -x \n\t"
+ "lsr r0 \n\t"
+ "st x, r0 \n\t"
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ IJMP
+ #endif
+
+ REPEAT(DEC(uECC_MAX_WORDS),
+ "ld r0, -x \n\t"
+ "ror r0 \n\t"
+ "st x, r0 \n\t")
+ "1: \n\t"
+ : "+x" (v)
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ : [num] "r" (num_words), [jump] "r" ((uint8_t)(3 * (num_words - 1)))
+ : "r0", "r30", "r31", "cc"
+ #else
+ : [num] "r" (num_words)
+ : "r0", "cc"
+ #endif
+ );
+}
+#define asm_rshift1 1
+
+#define ADD_RJPM_TABLE(N) \
+ "movw r30, %A[result] \n\t" \
+ "rjmp add_%=_" #N " \n\t"
+
+#define ADD_RJPM_DEST(N) \
+ "add_%=_" #N ":" \
+ "ld %[clb], x+ \n\t" \
+ "ld %[rb], y+ \n\t" \
+ "adc %[clb], %[rb] \n\t" \
+ "st z+, %[clb] \n\t"
+
+uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ volatile uECC_word_t *r = result;
+ uint8_t carry;
+ uint8_t right_byte;
+
+ __asm__ volatile (
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "ldi r30, pm_lo8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t"
+ "ldi r31, pm_hi8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t"
+ "sub r30, %[num] \n\t"
+ "sbc r31, __zero_reg__ \n\t"
+ #endif
+
+ "clc \n\t"
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ IJMP
+ REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE)
+ #endif
+
+ REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST)
+
+ "mov %[clb], __zero_reg__ \n\t"
+ "adc %[clb], %[clb] \n\t" /* Store carry bit. */
+
+ : "+x" (left), "+y" (right),
+ [clb] "=&r" (carry), [rb] "=&r" (right_byte)
+ : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2))
+ : "r30", "r31", "cc"
+ );
+ return carry;
+}
+#define asm_add 1
+
+#define SUB_RJPM_TABLE(N) \
+ "movw r30, %A[result] \n\t" \
+ "rjmp sub_%=_" #N " \n\t"
+
+#define SUB_RJPM_DEST(N) \
+ "sub_%=_" #N ":" \
+ "ld %[clb], x+ \n\t" \
+ "ld %[rb], y+ \n\t" \
+ "sbc %[clb], %[rb] \n\t" \
+ "st z+, %[clb] \n\t"
+
+uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ volatile uECC_word_t *r = result;
+ uint8_t carry;
+ uint8_t right_byte;
+
+ __asm__ volatile (
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ "ldi r30, pm_lo8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t"
+ "ldi r31, pm_hi8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t"
+ "sub r30, %[num] \n\t"
+ "sbc r31, __zero_reg__ \n\t"
+ #endif
+
+ "clc \n\t"
+ #if (uECC_MAX_WORDS != uECC_MIN_WORDS)
+ IJMP
+ REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE)
+ #endif
+
+ REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST)
+
+ "mov %[clb], __zero_reg__ \n\t"
+ "adc %[clb], %[clb] \n\t" /* Store carry bit. */
+
+ : "+x" (left), "+y" (right),
+ [clb] "=&r" (carry), [rb] "=&r" (right_byte)
+ : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2))
+ : "r30", "r31", "cc"
+ );
+ return carry;
+}
+#define asm_sub 1
+
+#if (uECC_OPTIMIZATION_LEVEL >= 3)
+
+#include "asm_avr_mult_square.inc"
+
+__attribute((noinline))
+uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ /* num_words should already be in r18. */
+ register wordcount_t r18 __asm__("r18") = num_words;
+
+ __asm__ volatile (
+ "push r18 \n\t"
+#if (uECC_MIN_WORDS == 20)
+ FAST_MULT_ASM_20
+ "pop r18 \n\t"
+ #if (uECC_MAX_WORDS > 20)
+ FAST_MULT_ASM_20_TO_24
+ #endif
+ #if (uECC_MAX_WORDS > 24)
+ FAST_MULT_ASM_24_TO_28
+ #endif
+ #if (uECC_MAX_WORDS > 28)
+ FAST_MULT_ASM_28_TO_32
+ #endif
+#elif (uECC_MIN_WORDS == 24)
+ FAST_MULT_ASM_24
+ "pop r18 \n\t"
+ #if (uECC_MAX_WORDS > 24)
+ FAST_MULT_ASM_24_TO_28
+ #endif
+ #if (uECC_MAX_WORDS > 28)
+ FAST_MULT_ASM_28_TO_32
+ #endif
+#elif (uECC_MIN_WORDS == 28)
+ FAST_MULT_ASM_28
+ "pop r18 \n\t"
+ #if (uECC_MAX_WORDS > 28)
+ FAST_MULT_ASM_28_TO_32
+ #endif
+#elif (uECC_MIN_WORDS == 32)
+ FAST_MULT_ASM_32
+ "pop r18 \n\t"
+#endif
+ "2: \n\t"
+ "eor r1, r1 \n\t"
+ : "+x" (left), "+y" (right), "+z" (result)
+ : "r" (r18)
+ : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r19", "r20",
+ "r21", "r22", "r23", "r24", "r25", "cc"
+ );
+}
+#define asm_mult 1
+
+#if uECC_SQUARE_FUNC
+__attribute((noinline))
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+ /* num_words should already be in r20. */
+ register wordcount_t r20 __asm__("r20") = num_words;
+
+ __asm__ volatile (
+ "push r20 \n\t"
+#if (uECC_MIN_WORDS == 20)
+ FAST_SQUARE_ASM_20
+ "pop r20 \n\t"
+ #if (uECC_MAX_WORDS > 20)
+ FAST_SQUARE_ASM_20_TO_24
+ #endif
+ #if (uECC_MAX_WORDS > 24)
+ FAST_SQUARE_ASM_24_TO_28
+ #endif
+ #if (uECC_MAX_WORDS > 28)
+ FAST_SQUARE_ASM_28_TO_32
+ #endif
+#elif (uECC_MIN_WORDS == 24)
+ FAST_SQUARE_ASM_24
+ "pop r20 \n\t"
+ #if (uECC_MAX_WORDS > 24)
+ FAST_SQUARE_ASM_24_TO_28
+ #endif
+ #if (uECC_MAX_WORDS > 28)
+ FAST_SQUARE_ASM_28_TO_32
+ #endif
+#elif (uECC_MIN_WORDS == 28)
+ FAST_SQUARE_ASM_28
+ "pop r20 \n\t"
+ #if (uECC_MAX_WORDS > 28)
+ FAST_SQUARE_ASM_28_TO_32
+ #endif
+#elif (uECC_MIN_WORDS == 32)
+ FAST_SQUARE_ASM_32
+ "pop r20 \n\t"
+#endif
+ "2: \n\t"
+ "eor r1, r1 \n\t"
+ : "+x" (left), "+z" (result)
+ : "r" (r20)
+ : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
+ "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
+ "r21", "r22", "r23", "r24", "r25", "r28", "r29", "cc"
+ );
+}
+#define asm_square 1
+#endif /* uECC_SQUARE_FUNC */
+
+#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */
+
+#if uECC_SUPPORTS_secp160r1
+static const struct uECC_Curve_t curve_secp160r1;
+static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
+ uint8_t carry = 0;
+ __asm__ volatile (
+ "in r30, __SP_L__ \n\t"
+ "in r31, __SP_H__ \n\t"
+ "sbiw r30, 24 \n\t"
+ "in r0, __SREG__ \n\t"
+ "cli \n\t"
+ "out __SP_H__, r31 \n\t"
+ "out __SREG__, r0 \n\t"
+ "out __SP_L__, r30 \n\t"
+
+ "adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes
+ (+ 1 since z initially points below the stack) */
+ "adiw r26, 40 \n\t" /* end of product */
+ "ld r18, -x \n\t" /* Load word. */
+ "lsr r18 \n\t" /* Shift. */
+ "st -z, r18 \n\t" /* Store the first result word. */
+
+ /* Now we just do the remaining words with the carry bit (using ROR) */
+ REPEAT(19,
+ "ld r18, -x \n\t"
+ "ror r18 \n\t"
+ "st -z, r18 \n\t")
+
+ "eor r18, r18 \n\t" /* r18 = 0 */
+ "ror r18 \n\t" /* get last bit */
+ "st -z, r18 \n\t" /* store it */
+
+ "sbiw r30, 3 \n\t" /* move z back to point at tmp */
+ /* now we add right */
+ "ld r18, x+ \n\t"
+ "st z+, r18 \n\t" /* the first 3 bytes do not need to be added */
+ "ld r18, x+ \n\t"
+ "st z+, r18 \n\t"
+ "ld r18, x+ \n\t"
+ "st z+, r18 \n\t"
+
+ "ld r18, x+ \n\t"
+ "ld r19, z \n\t"
+ "add r18, r19 \n\t"
+ "st z+, r18 \n\t"
+
+ /* Now we just do the remaining words with the carry bit (using ADC) */
+ REPEAT(16,
+ "ld r18, x+ \n\t"
+ "ld r19, z \n\t"
+ "adc r18, r19 \n\t"
+ "st z+, r18 \n\t")
+
+ /* Propagate over the remaining bytes of result */
+ "ld r18, z \n\t"
+ "adc r18, r1 \n\t"
+ "st z+, r18 \n\t"
+
+ "ld r18, z \n\t"
+ "adc r18, r1 \n\t"
+ "st z+, r18 \n\t"
+
+ "ld r18, z \n\t"
+ "adc r18, r1 \n\t"
+ "st z+, r18 \n\t"
+
+ "ld r18, z \n\t"
+ "adc r18, r1 \n\t"
+ "st z+, r18 \n\t"
+
+ "sbiw r30, 24 \n\t" /* move z back to point at tmp */
+ "sbiw r26, 40 \n\t" /* move x back to point at product */
+
+ /* add low bytes of tmp to product, storing in result */
+ "ld r18, z+ \n\t"
+ "ld r19, x+ \n\t"
+ "add r18, r19 \n\t"
+ "st y+, r18 \n\t"
+ REPEAT(19,
+ "ld r18, z+ \n\t"
+ "ld r19, x+ \n\t"
+ "adc r18, r19 \n\t"
+ "st y+, r18 \n\t")
+ "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
+ /* at this point x is at the end of product, y is at the end of result,
+ z is 20 bytes into tmp */
+ "sbiw r28, 20 \n\t" /* move y back to point at result */
+ "adiw r30, 4 \n\t" /* move z to point to the end of tmp */
+
+ /* do omega_mult again with the 4 relevant bytes */
+ /* z points to the end of tmp, x points to the end of product */
+ "ld r18, -z \n\t" /* Load word. */
+ "lsr r18 \n\t" /* Shift. */
+ "st -x, r18 \n\t" /* Store the first result word. */
+
+ "ld r18, -z \n\t"
+ "ror r18 \n\t"
+ "st -x, r18 \n\t"
+ "ld r18, -z \n\t"
+ "ror r18 \n\t"
+ "st -x, r18 \n\t"
+ "ld r18, -z \n\t"
+ "ror r18 \n\t"
+ "st -x, r18 \n\t"
+
+ "eor r18, r18 \n\t" /* r18 = 0 */
+ "ror r18 \n\t" /* get last bit */
+ "st -x, r18 \n\t" /* store it */
+
+ "sbiw r26, 3 \n\t" /* move x back to point at beginning */
+ /* now we add a copy of the 4 bytes */
+ "ld r18, z+ \n\t"
+ "st x+, r18 \n\t" /* the first 3 bytes do not need to be added */
+ "ld r18, z+ \n\t"
+ "st x+, r18 \n\t"
+ "ld r18, z+ \n\t"
+ "st x+, r18 \n\t"
+
+ "ld r18, z+ \n\t"
+ "ld r19, x \n\t"
+ "add r18, r19 \n\t"
+ "st x+, r18 \n\t"
+
+ /* Propagate over the remaining bytes */
+ "ld r18, x \n\t"
+ "adc r18, r1 \n\t"
+ "st x+, r18 \n\t"
+
+ "ld r18, x \n\t"
+ "adc r18, r1 \n\t"
+ "st x+, r18 \n\t"
+
+ "ld r18, x \n\t"
+ "adc r18, r1 \n\t"
+ "st x+, r18 \n\t"
+
+ "ld r18, x \n\t"
+ "adc r18, r1 \n\t"
+ "st x+, r18 \n\t"
+
+ /* now z points to the end of tmp, x points to the end of product
+ (y still points at result) */
+ "sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */
+ /* add into result */
+ "ld r18, x+ \n\t"
+ "ld r19, y \n\t"
+ "add r18, r19 \n\t"
+ "st y+, r18 \n\t"
+ REPEAT(7,
+ "ld r18, x+ \n\t"
+ "ld r19, y \n\t"
+ "adc r18, r19 \n\t"
+ "st y+, r18 \n\t")
+
+ /* Done adding, now propagate carry bit */
+ REPEAT(12,
+ "ld r18, y \n\t"
+ "adc r18, __zero_reg__ \n\t"
+ "st y+, r18 \n\t")
+
+ "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
+ "sbiw r28, 20 \n\t" /* move y back to point at result */
+
+ "sbiw r30, 1 \n\t" /* fix stack pointer */
+ "in r0, __SREG__ \n\t"
+ "cli \n\t"
+ "out __SP_H__, r31 \n\t"
+ "out __SREG__, r0 \n\t"
+ "out __SP_L__, r30 \n\t"
+
+ : "+x" (product), [carry] "+r" (carry)
+ : "y" (result)
+ : "r0", "r18", "r19", "r30", "r31", "cc"
+ );
+
+ if (carry > 0) {
+ --carry;
+ uECC_vli_sub(result, result, curve_secp160r1.p, 20);
+ }
+ if (carry > 0) {
+ uECC_vli_sub(result, result, curve_secp160r1.p, 20);
+ }
+ if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, 20) > 0) {
+ uECC_vli_sub(result, result, curve_secp160r1.p, 20);
+ }
+}
+#define asm_mmod_fast_secp160r1 1
+#endif /* uECC_SUPPORTS_secp160r1 */
+
+#if uECC_SUPPORTS_secp256k1
+static const struct uECC_Curve_t curve_secp256k1;
+static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) {
+ uint8_t carry = 0;
+ __asm__ volatile (
+ "in r30, __SP_L__ \n\t"
+ "in r31, __SP_H__ \n\t"
+ "sbiw r30, 37 \n\t"
+ "in r0, __SREG__ \n\t"
+ "cli \n\t"
+ "out __SP_H__, r31 \n\t"
+ "out __SREG__, r0 \n\t"
+ "out __SP_L__, r30 \n\t"
+
+ "adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */
+ "adiw r26, 32 \n\t" /* product + uECC_WORDS */
+ "ldi r25, 0x03 \n\t"
+ "ldi r24, 0xD1 \n\t"
+ "ld r18, x+ \n\t"
+ "ld r19, x+ \n\t"
+ "ld r20, x+ \n\t"
+ "ld r21, x+ \n\t"
+
+ "mul r24, r18 \n\t"
+ "st z+, r0 \n\t"
+ "mov r22, r1 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "mul r24, r19 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t" /* can't overflow */
+ "mul r25, r18 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t" /* can't overflow */
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "mul r24, r20 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r19 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "mul r24, r21 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "mul r25, r20 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ /* now we start adding the 2^32 part as well */
+ "add r23, r18 \n\t" // 28
+ "adc r22, r22 \n\t"
+ "ld r18, x+ \n\t"
+ "mul r24, r18 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r21 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r19 \n\t" // 27
+ "adc r23, r23 \n\t"
+ "ld r19, x+ \n\t"
+ "mul r24, r19 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "mul r25, r18 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ REPEAT(6, // 26 - 3
+ "add r23, r20 \n\t"
+ "adc r22, r22 \n\t"
+ "ld r20, x+ \n\t"
+ "mul r24, r20 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r19 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r21 \n\t"
+ "adc r23, r23 \n\t"
+ "ld r21, x+ \n\t"
+ "mul r24, r21 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "mul r25, r20 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "add r23, r18 \n\t"
+ "adc r22, r22 \n\t"
+ "ld r18, x+ \n\t"
+ "mul r24, r18 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r21 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r19 \n\t"
+ "adc r23, r23 \n\t"
+ "ld r19, x+ \n\t"
+ "mul r24, r19 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "mul r25, r18 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t")
+
+ "add r23, r20 \n\t" // 2
+ "adc r22, r22 \n\t"
+ "ld r20, x+ \n\t"
+ "mul r24, r20 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r19 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r21 \n\t" // 1
+ "adc r23, r23 \n\t"
+ "ld r21, x+ \n\t"
+ "mul r24, r21 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "mul r25, r20 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ /* Now finish the carries etc */
+ "add r23, r18 \n\t"
+ "adc r22, r22 \n\t"
+ "mul r25, r21 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r19 \n\t"
+ "adc r23, r23 \n\t"
+ "st z+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "add r23, r20 \n\t"
+ "adc r22, r22 \n\t"
+ "st z+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r21 \n\t"
+ "adc r23, r23 \n\t"
+ "st z+, r22 \n\t"
+ "st z+, r23 \n\t"
+ "eor r1, r1 \n\t" /* make r1 be 0 again */
+
+ "sbiw r30, 37 \n\t" /* move z back to point at tmp */
+ "subi r26, 64 \n\t" /* move x back to point at product */
+ "sbc r27, __zero_reg__ \n\t"
+
+ /* add low bytes of tmp to product, storing in result */
+ "ld r18, z+ \n\t"
+ "ld r19, x+ \n\t"
+ "add r18, r19 \n\t"
+ "st y+, r18 \n\t"
+ REPEAT(31,
+ "ld r18, z+ \n\t"
+ "ld r19, x+ \n\t"
+ "adc r18, r19 \n\t"
+ "st y+, r18 \n\t")
+
+ "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
+ /* at this point x is at the end of product, y is at the end of result,
+ z is 32 bytes into tmp */
+ "sbiw r28, 32 \n\t" /* move y back to point at result */
+
+ /* do omega_mult again with the 5 relevant bytes */
+ /* z points to tmp + uECC_WORDS, x points to the end of product */
+ "sbiw r26, 32 \n\t" /* shift x back to point into the product buffer
+ (we can overwrite it now) */
+ "ld r18, z+ \n\t"
+ "ld r19, z+ \n\t"
+ "ld r20, z+ \n\t"
+ "ld r21, z+ \n\t"
+
+ "mul r24, r18 \n\t"
+ "st x+, r0 \n\t"
+ "mov r22, r1 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "mul r24, r19 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t" /* can't overflow */
+ "mul r25, r18 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t" /* can't overflow */
+ "st x+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "mul r24, r20 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r19 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st x+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "mul r24, r21 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "mul r25, r20 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st x+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "add r23, r18 \n\t"
+ "adc r22, r22 \n\t"
+ "ld r18, z+ \n\t"
+ "mul r24, r18 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "mul r25, r21 \n\t"
+ "add r23, r0 \n\t"
+ "adc r22, r1 \n\t"
+ "st x+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ /* Now finish the carries etc */
+ "add r22, r19 \n\t"
+ "adc r23, r23 \n\t"
+ "mul r25, r18 \n\t"
+ "add r22, r0 \n\t"
+ "adc r23, r1 \n\t"
+ "st x+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "add r23, r20 \n\t"
+ "adc r22, r22 \n\t"
+ "st x+, r23 \n\t"
+ "ldi r23, 0 \n\t"
+
+ "add r22, r21 \n\t"
+ "adc r23, r23 \n\t"
+ "st x+, r22 \n\t"
+ "ldi r22, 0 \n\t"
+
+ "add r23, r18 \n\t"
+ "adc r22, r22 \n\t"
+ "st x+, r23 \n\t"
+ "st x+, r22 \n\t"
+ "eor r1, r1 \n\t" /* make r1 be 0 again */
+
+ /* now z points to the end of tmp, x points to the end of product
+ (y still points at result) */
+ "sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */
+ /* add into result */
+ "ld r18, x+ \n\t"
+ "ld r19, y \n\t"
+ "add r18, r19 \n\t"
+ "st y+, r18 \n\t"
+ REPEAT(9,
+ "ld r18, x+ \n\t"
+ "ld r19, y \n\t"
+ "adc r18, r19 \n\t"
+ "st y+, r18 \n\t")
+
+ /* Done adding, now propagate carry bit */
+ REPEAT(22,
+ "ld r18, y \n\t"
+ "adc r18, __zero_reg__ \n\t"
+ "st y+, r18 \n\t")
+
+ "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */
+ "sbiw r28, 32 \n\t" /* move y back to point at result */
+
+ "sbiw r30, 1 \n\t" /* fix stack pointer */
+ "in r0, __SREG__ \n\t"
+ "cli \n\t"
+ "out __SP_H__, r31 \n\t"
+ "out __SREG__, r0 \n\t"
+ "out __SP_L__, r30 \n\t"
+
+ : "+x" (product), [carry] "+r" (carry)
+ : "y" (result)
+ : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc"
+ );
+
+ if (carry > 0) {
+ --carry;
+ uECC_vli_sub(result, result, curve_secp256k1.p, 32);
+ }
+ if (carry > 0) {
+ uECC_vli_sub(result, result, curve_secp256k1.p, 32);
+ }
+ if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, 32) > 0) {
+ uECC_vli_sub(result, result, curve_secp256k1.p, 32);
+ }
+}
+#define asm_mmod_fast_secp256k1 1
+#endif /* uECC_SUPPORTS_secp256k1 */
+
+#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */
+
+/* ---- "Small" implementations ---- */
+
+#if !asm_add
+uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ volatile uECC_word_t *r = result;
+ uint8_t carry = 0;
+ uint8_t left_byte;
+ uint8_t right_byte;
+
+ __asm__ volatile (
+ "clc \n\t"
+
+ "1: \n\t"
+ "ld %[left], x+ \n\t" /* Load left byte. */
+ "ld %[right], y+ \n\t" /* Load right byte. */
+ "adc %[left], %[right] \n\t" /* Add. */
+ "st z+, %[left] \n\t" /* Store the result. */
+ "dec %[i] \n\t"
+ "brne 1b \n\t"
+
+ "adc %[carry], %[carry] \n\t" /* Store carry bit. */
+
+ : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words),
+ [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte)
+ :
+ : "cc"
+ );
+ return carry;
+}
+#define asm_add 1
+#endif
+
+#if !asm_sub
+uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ volatile uECC_word_t *r = result;
+ uint8_t borrow = 0;
+ uint8_t left_byte;
+ uint8_t right_byte;
+
+ __asm__ volatile (
+ "clc \n\t"
+
+ "1: \n\t"
+ "ld %[left], x+ \n\t" /* Load left byte. */
+ "ld %[right], y+ \n\t" /* Load right byte. */
+ "sbc %[left], %[right] \n\t" /* Subtract. */
+ "st z+, %[left] \n\t" /* Store the result. */
+ "dec %[i] \n\t"
+ "brne 1b \n\t"
+
+ "adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */
+
+ : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (i),
+ [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte)
+ :
+ : "cc"
+ );
+ return borrow;
+}
+#define asm_sub 1
+#endif
+
+#if !asm_mult
+__attribute((noinline))
+uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ volatile uECC_word_t *r = result;
+ uint8_t r0 = 0;
+ uint8_t r1 = 0;
+ uint8_t r2 = 0;
+ uint8_t zero = 0;
+ uint8_t k, i;
+
+ __asm__ volatile (
+ "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */
+
+ "1: \n\t"
+ "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */
+
+ "add r28, %[k] \n\t" /* pre-add right ptr */
+ "adc r29, %[zero] \n\t"
+
+ "2: \n\t"
+ "ld r0, x+ \n\t"
+ "ld r1, -y \n\t"
+ "mul r0, r1 \n\t"
+
+ "add %[r0], r0 \n\t"
+ "adc %[r1], r1 \n\t"
+ "adc %[r2], %[zero] \n\t"
+
+ "inc %[i] \n\t"
+ "cp %[i], %[k] \n\t"
+ "brlo 2b \n\t" /* loop if i < k */
+
+ "sub r26, %[k] \n\t" /* fix up left ptr */
+ "sbc r27, %[zero] \n\t"
+
+ "st z+, %[r0] \n\t" /* Store the result. */
+ "mov %[r0], %[r1] \n\t"
+ "mov %[r1], %[r2] \n\t"
+ "mov %[r2], %[zero] \n\t"
+
+ "inc %[k] \n\t"
+ "cp %[k], %[num] \n\t"
+ "brlo 1b \n\t" /* loop if k < num_words */
+
+ /* second half */
+ "mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */
+ "add r28, %[num] \n\t" /* move right ptr to point at the end of right */
+ "adc r29, %[zero] \n\t"
+
+ "1: \n\t"
+ "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */
+
+ "2: \n\t"
+ "ld r0, x+ \n\t"
+ "ld r1, -y \n\t"
+ "mul r0, r1 \n\t"
+
+ "add %[r0], r0 \n\t"
+ "adc %[r1], r1 \n\t"
+ "adc %[r2], %[zero] \n\t"
+
+ "inc %[i] \n\t"
+ "cp %[i], %[k] \n\t"
+ "brlo 2b \n\t" /* loop if i < k */
+
+ "add r28, %[k] \n\t" /* fix up right ptr */
+ "adc r29, %[zero] \n\t"
+
+ "st z+, %[r0] \n\t" /* Store the result. */
+ "mov %[r0], %[r1] \n\t"
+ "mov %[r1], %[r2] \n\t"
+ "mov %[r2], %[zero] \n\t"
+
+ "dec %[k] \n\t"
+ "sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time
+ we start 1 higher) */
+ "sbc r27, %[zero] \n\t"
+
+ "cp %[k], %[zero] \n\t"
+ "brne 1b \n\t" /* loop if k > 0 */
+
+ "st z+, %[r0] \n\t" /* Store last result byte. */
+ "eor r1, r1 \n\t" /* fix r1 to be 0 again */
+
+ : "+z" (result), "+x" (left), "+y" (right),
+ [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2),
+ [zero] "+r" (zero), [num] "+r" (num_words),
+ [k] "=&r" (k), [i] "=&r" (i)
+ :
+ : "r0", "cc"
+ );
+}
+#define asm_mult 1
+#endif
+
+#if (uECC_SQUARE_FUNC && !asm_square)
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+ volatile uECC_word_t *r = result;
+ uint8_t r0 = 0;
+ uint8_t r1 = 0;
+ uint8_t r2 = 0;
+ uint8_t zero = 0;
+ uint8_t k;
+
+ __asm__ volatile (
+ "ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */
+
+ "1: \n\t"
+
+ "movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */
+ "movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */
+ "cp %[k], %[num] \n\t"
+ "brlo 2f \n\t"
+ "breq 2f \n\t"
+
+ /* when k > num_words, we start from (k - num_words) on the 'left' ptr */
+ "add r26, %[k] \n\t"
+ "adc r27, %[zero] \n\t"
+ "sub r26, %[num] \n\t"
+ "sbc r27, %[zero] \n\t"
+ "add r30, %[num] \n\t" /* move right ptr to point at the end */
+ "adc r31, %[zero] \n\t"
+ "rjmp 3f \n\t"
+
+ "2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */
+ "add r30, %[k] \n\t" /* pre-add 'right' ptr */
+ "adc r31, %[zero] \n\t"
+
+ "3: \n\t"
+ "ld r0, x+ \n\t"
+ "cp r26, r30 \n\t" /* if left == right here, then we are done after this mult
+ (and we don't need to double) */
+ "breq 4f \n\t"
+ "ld r1, -z \n\t"
+ "mul r0, r1 \n\t"
+
+ /* add twice since it costs the same as doubling */
+ "add %[r0], r0 \n\t"
+ "adc %[r1], r1 \n\t"
+ "adc %[r2], %[zero] \n\t"
+ "add %[r0], r0 \n\t"
+ "adc %[r1], r1 \n\t"
+ "adc %[r2], %[zero] \n\t"
+
+ "cpse r26, r30 \n\t" /* if left == right here, then we are done */
+ "rjmp 3b \n\t"
+ "rjmp 5f \n\t" /* skip code for non-doubled mult */
+
+ "4: \n\t"
+ "ld r1, -z \n\t"
+ "mul r0, r1 \n\t"
+ "add %[r0], r0 \n\t"
+ "adc %[r1], r1 \n\t"
+ "adc %[r2], %[zero] \n\t"
+
+ "5: \n\t"
+ "movw r30, %[result] \n\t" /* make z point to result */
+ "st z+, %[r0] \n\t" /* Store the result. */
+ "movw %[result], r30 \n\t" /* update result ptr*/
+ "mov %[r0], %[r1] \n\t"
+ "mov %[r1], %[r2] \n\t"
+ "mov %[r2], %[zero] \n\t"
+
+ "inc %[k] \n\t"
+ "cp %[k], %[max] \n\t"
+ "brlo 1b \n\t" /* loop if k < num_words * 2 */
+
+ "movw r30, %[result] \n\t" /* make z point to result */
+ "st z+, %[r0] \n\t" /* Store last result byte. */
+ "eor r1, r1 \n\t" /* fix r1 to be 0 again */
+
+ : [result] "+r" (r),
+ [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero),
+ [k] "=&a" (k)
+ : [orig] "r" (left), [max] "r" ((uint8_t)(2 * num_words)),
+ [num] "r" (num_words)
+ : "r0", "r26", "r27", "r30", "r31", "cc"
+ );
+}
+#define asm_square 1
+#endif /* uECC_SQUARE_FUNC && !asm_square */
+
+#endif /* _UECC_ASM_AVR_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc
new file mode 100644
index 00000000..7ae08bce
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/asm_avr_mult_square.inc
@@ -0,0 +1,26311 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_ASM_AVR_MULT_SQUARE_H_
+#define _UECC_ASM_AVR_MULT_SQUARE_H_
+
+#define FAST_MULT_ASM_20 \
+ "adiw r30, 10 \n\t" \
+ "adiw r28, 10 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r21, y+ \n\t" \
+ "ldi r25, 0 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "st z+, r24 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "sbiw r30, 30 \n\t" \
+ "sbiw r28, 20 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r21, y+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r20, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r21, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t"
+
+#define FAST_MULT_ASM_20_TO_24 \
+ "cpi r18, 20 \n\t" \
+ "brne 1f \n\t" \
+ "jmp 2f \n\t" \
+ "1: \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r6, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r7, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r8, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r9, y+ \n\t" \
+ "sbiw r26, 24 \n\t" \
+ "sbiw r28, 24 \n\t" \
+ "sbiw r30, 20 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ \
+ "mul r2, r14 \n\t" \
+ "mov r19, r0 \n\t" \
+ "mov r20, r1 \n\t" \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "mul r11, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r12, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r13, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "mul r12, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r13, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "mul r13, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "mul r5, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "st z+, r21 \n\t" \
+ "st z+, r19 \n\t" \
+ "adiw r26, 4 \n\t" \
+ "adiw r28, 4 \n\t"
+
+#define FAST_MULT_ASM_24 \
+ "adiw r30, 20 \n\t" \
+ "adiw r28, 20 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ldi r25, 0 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "st z+, r24 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "sbiw r30, 18 \n\t" \
+ "sbiw r28, 14 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r21, y+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "sbiw r30, 38 \n\t" \
+ "sbiw r28, 24 \n\t" \
+ "sbiw r26, 14 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r21, y+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r20, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r21, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "st z+, r22 \n\t" \
+ "st z+, r23 \n\t"
+
+#define FAST_MULT_ASM_24_TO_28 \
+ "cpi r18, 24 \n\t" \
+ "brne 1f \n\t" \
+ "jmp 2f \n\t" \
+ "1: \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r6, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r7, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r8, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r9, y+ \n\t" \
+ "sbiw r26, 28 \n\t" \
+ "sbiw r28, 28 \n\t" \
+ "sbiw r30, 24 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ \
+ "mul r2, r14 \n\t" \
+ "mov r19, r0 \n\t" \
+ "mov r20, r1 \n\t" \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "mul r11, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r12, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r13, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "mul r12, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r13, r8 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "mul r13, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "mul r5, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "st z+, r19 \n\t" \
+ "st z+, r20 \n\t" \
+ "adiw r26, 4 \n\t" \
+ "adiw r28, 4 \n\t"
+
+#define FAST_MULT_ASM_28 \
+ "adiw r30, 20 \n\t" \
+ "adiw r28, 20 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ldi r25, 0 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "sbiw r30, 26 \n\t" \
+ "sbiw r28, 18 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r21, y+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "mul r9, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "st z+, r22 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "sbiw r30, 46 \n\t" \
+ "sbiw r28, 28 \n\t" \
+ "sbiw r26, 18 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r21, y+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r20, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r21, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "st z+, r24 \n\t" \
+ "st z+, r22 \n\t"
+
+#define FAST_MULT_ASM_28_TO_32 \
+ "cpi r18, 28 \n\t" \
+ "brne 1f \n\t" \
+ "jmp 2f \n\t" \
+ "1: \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r6, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r7, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r8, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r9, y+ \n\t" \
+ "sbiw r26, 32 \n\t" \
+ "sbiw r28, 32 \n\t" \
+ "sbiw r30, 28 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ \
+ "mul r2, r14 \n\t" \
+ "mov r19, r0 \n\t" \
+ "mov r20, r1 \n\t" \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r25 \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r25 \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "ld r0, z \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r25 \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "mul r11, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r12, r8 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r13, r7 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "mul r12, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r13, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "mul r13, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "ldi r19, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "st z+, r20 \n\t" \
+ \
+ "ldi r20, 0 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r20, r25 \n\t" \
+ "st z+, r21 \n\t" \
+ \
+ "ldi r21, 0 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r20, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "st z+, r19 \n\t" \
+ \
+ "mul r5, r9 \n\t" \
+ "add r20, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "st z+, r20 \n\t" \
+ "st z+, r21 \n\t"
+ /* Not necessary to move ptrs since we don't support sizes > 32 */
+
+#define FAST_MULT_ASM_32 \
+ "adiw r30, 30 \n\t" \
+ "adiw r28, 30 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ldi r25, 0 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "sbiw r30, 14 \n\t" \
+ "sbiw r28, 12 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r21, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "st z+, r22 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "sbiw r30, 34 \n\t" \
+ "sbiw r28, 22 \n\t" \
+ "sbiw r26, 12 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r21, y+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r20, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r21, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "st z+, r24 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "sbiw r30, 54 \n\t" \
+ "sbiw r28, 32 \n\t" \
+ "sbiw r26, 22 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r18, y+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r19, y+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r20, y+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r21, y+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r20, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r21, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r18, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r19, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r20, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r21, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r25 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r19 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r20 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r21 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t"
+
+#define FAST_SQUARE_ASM_20 \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r14, x+ \n\t" \
+ "ld r15, x+ \n\t" \
+ "ld r16, x+ \n\t" \
+ "ld r17, x+ \n\t" \
+ "ld r18, x+ \n\t" \
+ "ld r19, x+ \n\t" \
+ "ld r20, x+ \n\t" \
+ "ld r21, x+ \n\t" \
+ "push r26 \n\t" \
+ "push r27 \n\t" \
+ "ldi r25, 0 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r2 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r3 \n\t" \
+ "lsl r0 \n\t" \
+ "rol r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r4 \n\t" \
+ "lsl r0 \n\t" \
+ "rol r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r10 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r6, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r11 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r7, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r7, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r8, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r8, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r9, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r10, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r10, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r11, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r12, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r4, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r12, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r13, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r6, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r12, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r13, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r14, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r8, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r12, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r13, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r14, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r15, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r10, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r12, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r13, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r14, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r15, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r11, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r12, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r16, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r12, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r13, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r14, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r15, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r16, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r13, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r14, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r17, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r14, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r15, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r16, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r17, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r15, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r16, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r18, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r16, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r17, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "mul r18, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r17, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r18, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r19, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r27 \n\t" \
+ "adc r24, r26 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r26, 0 \n\t" \
+ "mul r18, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r27, r1 \n\t" \
+ "mul r19, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "adc r26, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r27 \n\t" \
+ "rol r26 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r27, r22 \n\t" \
+ "adc r26, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r19, r21 \n\t" \
+ "lsl r0 \n\t" \
+ "rol r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "add r27, r0 \n\t" \
+ "adc r26, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r20, r20 \n\t" \
+ "add r27, r0 \n\t" \
+ "adc r26, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r27 \n\t" \
+ \
+ "ldi r27, 0 \n\t" \
+ "mul r20, r21 \n\t" \
+ "lsl r0 \n\t" \
+ "rol r1 \n\t" \
+ "adc r27, r25 \n\t" \
+ "add r26, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r27, r25 \n\t" \
+ "st z+, r26 \n\t" \
+ \
+ "mul r21, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r27, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r27 \n\t" \
+ "pop r27 \n\t" \
+ "pop r26 \n\t"
+
+#define FAST_SQUARE_ASM_20_TO_24 \
+ "cpi r20, 20 \n\t" \
+ "brne 1f \n\t" \
+ "jmp 2f \n\t" \
+ "1: \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "sbiw r26, 24 \n\t" \
+ "sbiw r30, 20 \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ \
+ "mul r2, r6 \n\t" \
+ "mov r10, r0 \n\t" \
+ "mov r11, r1 \n\t" \
+ "mov r12, r25 \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ \
+ "mov r14, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ \
+ "mov r15, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r17, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r18, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r19, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r21, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r22, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r23, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r24, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r28, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r29, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ \
+ "lsl r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r16 \n\t" \
+ "rol r17 \n\t" \
+ "rol r18 \n\t" \
+ "rol r19 \n\t" \
+ "rol r21 \n\t" \
+ "rol r22 \n\t" \
+ "rol r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "ld r0, z \n\t" \
+ "add r10, r0 \n\t" \
+ "st z+, r10 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r11, r0 \n\t" \
+ "st z+, r11 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r12, r0 \n\t" \
+ "st z+, r12 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r13, r0 \n\t" \
+ "st z+, r13 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r14, r0 \n\t" \
+ "st z+, r14 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r15, r0 \n\t" \
+ "st z+, r15 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r16, r0 \n\t" \
+ "st z+, r16 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r17, r0 \n\t" \
+ "st z+, r17 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r18, r0 \n\t" \
+ "st z+, r18 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r19, r0 \n\t" \
+ "st z+, r19 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r21, r0 \n\t" \
+ "st z+, r21 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r22, r0 \n\t" \
+ "st z+, r22 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r23, r0 \n\t" \
+ "st z+, r23 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r24, r0 \n\t" \
+ "st z+, r24 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "bst r28, 0 \n\t" \
+ "lsr r29 \n\t" \
+ "ror r28 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r10, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r11, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r12, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r14, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r15, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "lsl r28 \n\t" \
+ "bld r28, 0 \n\t" \
+ "rol r29 \n\t" \
+ "rol r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "ld r0, z \n\t" \
+ "add r28, r0 \n\t" \
+ "st z+, r28 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r29, r0 \n\t" \
+ "st z+, r29 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r10, r0 \n\t" \
+ "st z+, r10 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r11, r0 \n\t" \
+ "st z+, r11 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r12, r0 \n\t" \
+ "st z+, r12 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r13, r0 \n\t" \
+ "st z+, r13 \n\t" \
+ "adc r14, r25 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "mul r2, r2 \n\t" \
+ "mov r16, r0 \n\t" \
+ "mov r17, r1 \n\t" \
+ "mul r3, r3 \n\t" \
+ "mov r18, r0 \n\t" \
+ "mov r19, r1 \n\t" \
+ "mul r4, r4 \n\t" \
+ "mov r21, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ "mul r5, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "add r16, r14 \n\t" \
+ "adc r17, r15 \n\t" \
+ "adc r18, r25 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "mul r7, r5 \n\t" \
+ "mov r14, r0 \n\t" \
+ "mov r15, r1 \n\t" \
+ "mov r28, r25 \n\t" \
+ "mul r8, r4 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r9, r3 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mov r29, r25 \n\t" \
+ "mul r8, r5 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r4 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mov r10, r25 \n\t" \
+ "mul r9, r5 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mov r11, r25 \n\t" \
+ "mul r2, r5 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mov r12, r25 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ \
+ "lsl r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "rol r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "adc r24, r25 \n\t" \
+ "add r16, r14 \n\t" \
+ "adc r17, r15 \n\t" \
+ "adc r18, r28 \n\t" \
+ "adc r19, r29 \n\t" \
+ "adc r21, r10 \n\t" \
+ "adc r22, r11 \n\t" \
+ "adc r23, r12 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "st z+, r16 \n\t" \
+ "st z+, r17 \n\t" \
+ "st z+, r18 \n\t" \
+ "st z+, r19 \n\t" \
+ "st z+, r21 \n\t" \
+ "st z+, r22 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t" \
+ "adiw r26, 4 \n\t"
+
+#define FAST_SQUARE_ASM_24 \
+ "ldi r25, 0 \n\t" \
+ "movw r28, r26 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "adiw r28, 20 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "adiw r30, 20 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul 2, 12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "st z+, r24 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "sbiw r26, 4 \n\t" \
+ "sbiw r30, 28 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r14, x+ \n\t" \
+ "ld r15, x+ \n\t" \
+ "ld r16, x+ \n\t" \
+ "ld r17, x+ \n\t" \
+ "ld r18, x+ \n\t" \
+ "ld r19, x+ \n\t" \
+ "ld r20, x+ \n\t" \
+ "ld r21, x+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r2 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r10 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r6, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r11 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r7, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r8, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r9, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r10, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r11, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r12, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r3, r2 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r2 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r13, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r4, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r5, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r6, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r14, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r5, r4 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r6, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r4 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r7, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r15, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r6, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r7, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r8, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r16, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r8, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r9, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r10, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r17, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r10, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r11, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r11, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r12, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r18, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r12, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r13, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r13, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r14, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r19, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r14, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r15, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r15, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r16, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r20, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r16, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r17, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r17, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r18, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r21, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r18, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r19, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r19, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r20, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r2, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r20, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r21, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r21, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r28 \n\t" \
+ \
+ "ldi r28, 0 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "st z+, r29 \n\t" \
+ \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r28 \n\t"
+
+#define FAST_SQUARE_ASM_24_TO_28 \
+ "cpi r20, 24 \n\t" \
+ "brne 1f \n\t" \
+ "jmp 2f \n\t" \
+ "1: \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "sbiw r26, 28 \n\t" \
+ "sbiw r30, 24 \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ \
+ "mul r2, r6 \n\t" \
+ "mov r10, r0 \n\t" \
+ "mov r11, r1 \n\t" \
+ "mov r12, r25 \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ \
+ "mov r14, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ \
+ "mov r15, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r17, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r18, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r19, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r21, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r22, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r23, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r24, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r28, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r29, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ \
+ "lsl r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r16 \n\t" \
+ "rol r17 \n\t" \
+ "rol r18 \n\t" \
+ "rol r19 \n\t" \
+ "rol r21 \n\t" \
+ "rol r22 \n\t" \
+ "rol r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "ld r0, z \n\t" \
+ "add r10, r0 \n\t" \
+ "st z+, r10 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r11, r0 \n\t" \
+ "st z+, r11 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r12, r0 \n\t" \
+ "st z+, r12 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r13, r0 \n\t" \
+ "st z+, r13 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r14, r0 \n\t" \
+ "st z+, r14 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r15, r0 \n\t" \
+ "st z+, r15 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r16, r0 \n\t" \
+ "st z+, r16 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r17, r0 \n\t" \
+ "st z+, r17 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r18, r0 \n\t" \
+ "st z+, r18 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r19, r0 \n\t" \
+ "st z+, r19 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r21, r0 \n\t" \
+ "st z+, r21 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r22, r0 \n\t" \
+ "st z+, r22 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r23, r0 \n\t" \
+ "st z+, r23 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r24, r0 \n\t" \
+ "st z+, r24 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "bst r28, 0 \n\t" \
+ "lsr r29 \n\t" \
+ "ror r28 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r10, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r11, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r12, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r14, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r15, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r17, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r18, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r19, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "lsl r28 \n\t" \
+ "bld r28, 0 \n\t" \
+ "rol r29 \n\t" \
+ "rol r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r16 \n\t" \
+ "rol r17 \n\t" \
+ "rol r18 \n\t" \
+ "rol r19 \n\t" \
+ "ld r0, z \n\t" \
+ "add r28, r0 \n\t" \
+ "st z+, r28 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r29, r0 \n\t" \
+ "st z+, r29 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r10, r0 \n\t" \
+ "st z+, r10 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r11, r0 \n\t" \
+ "st z+, r11 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r12, r0 \n\t" \
+ "st z+, r12 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r13, r0 \n\t" \
+ "st z+, r13 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r14, r0 \n\t" \
+ "st z+, r14 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r15, r0 \n\t" \
+ "st z+, r15 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r16, r0 \n\t" \
+ "st z+, r16 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r17, r0 \n\t" \
+ "st z+, r17 \n\t" \
+ "adc r18, r25 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "mul r2, r2 \n\t" \
+ "mov r21, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ "mul r3, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r4 \n\t" \
+ "mov r28, r0 \n\t" \
+ "mov r29, r1 \n\t" \
+ "mul r5, r5 \n\t" \
+ "mov r10, r0 \n\t" \
+ "mov r11, r1 \n\t" \
+ "add r21, r18 \n\t" \
+ "adc r22, r19 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "mul r7, r5 \n\t" \
+ "mov r18, r0 \n\t" \
+ "mov r19, r1 \n\t" \
+ "mov r12, r25 \n\t" \
+ "mul r8, r4 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r9, r3 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r8, r5 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r9, r4 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mov r14, r25 \n\t" \
+ "mul r9, r5 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mov r15, r25 \n\t" \
+ "mul r2, r5 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ \
+ "lsl r18 \n\t" \
+ "rol r19 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r16 \n\t" \
+ "adc r11, r25 \n\t" \
+ "add r21, r18 \n\t" \
+ "adc r22, r19 \n\t" \
+ "adc r23, r12 \n\t" \
+ "adc r24, r13 \n\t" \
+ "adc r28, r14 \n\t" \
+ "adc r29, r15 \n\t" \
+ "adc r10, r16 \n\t" \
+ "adc r11, r25 \n\t" \
+ \
+ "st z+, r21 \n\t" \
+ "st z+, r22 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t" \
+ "st z+, r28 \n\t" \
+ "st z+, r29 \n\t" \
+ "st z+, r10 \n\t" \
+ "st z+, r11 \n\t" \
+ "adiw r26, 4 \n\t"
+
+#define FAST_SQUARE_ASM_28 \
+ "ldi r25, 0 \n\t" \
+ "movw r28, r26 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "adiw r28, 20 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "adiw r30, 20 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul 2, 12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "sbiw r26, 8 \n\t" \
+ "sbiw r30, 36 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r14, x+ \n\t" \
+ "ld r15, x+ \n\t" \
+ "ld r16, x+ \n\t" \
+ "ld r17, x+ \n\t" \
+ "ld r18, x+ \n\t" \
+ "ld r19, x+ \n\t" \
+ "ld r20, x+ \n\t" \
+ "ld r21, x+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r2 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r10 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r6, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r11 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r7, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r8, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r9, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r10, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r11, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r12, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r3, r2 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r2 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r13, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r4, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r5, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r6, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r14, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r5, r4 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r6, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r4 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r7, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r15, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r6, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r7, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r8, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r16, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r7, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r8, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r8, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r9, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r17, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r8, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r9, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r10, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r18, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r9, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r10, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r11, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r19, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r10, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r11, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r11, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r12, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r20, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r12, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r13, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r13, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r14, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r21, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r14, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r15, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r15, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r16, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r2, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r16, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r17, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r17, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r18, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r18, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r19, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r19, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r20, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r20, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r21, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r21, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r6, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r4, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r6, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r7, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r6, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r7, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r7, r9 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r8, r8 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r28 \n\t" \
+ \
+ "ldi r28, 0 \n\t" \
+ "mul r8, r9 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "st z+, r29 \n\t" \
+ \
+ "mul r9, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r28 \n\t"
+
+#define FAST_SQUARE_ASM_28_TO_32 \
+ "cpi r20, 28 \n\t" \
+ "brne 1f \n\t" \
+ "jmp 2f \n\t" \
+ "1: \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "sbiw r26, 32 \n\t" \
+ "sbiw r30, 28 \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ \
+ "mul r2, r6 \n\t" \
+ "mov r10, r0 \n\t" \
+ "mov r11, r1 \n\t" \
+ "mov r12, r25 \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ \
+ "mov r14, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ \
+ "mov r15, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r17, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r18, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r19, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r21, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r22, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r23, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r24, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r28, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r29, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ \
+ "lsl r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r16 \n\t" \
+ "rol r17 \n\t" \
+ "rol r18 \n\t" \
+ "rol r19 \n\t" \
+ "rol r21 \n\t" \
+ "rol r22 \n\t" \
+ "rol r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "ld r0, z \n\t" \
+ "add r10, r0 \n\t" \
+ "st z+, r10 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r11, r0 \n\t" \
+ "st z+, r11 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r12, r0 \n\t" \
+ "st z+, r12 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r13, r0 \n\t" \
+ "st z+, r13 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r14, r0 \n\t" \
+ "st z+, r14 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r15, r0 \n\t" \
+ "st z+, r15 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r16, r0 \n\t" \
+ "st z+, r16 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r17, r0 \n\t" \
+ "st z+, r17 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r18, r0 \n\t" \
+ "st z+, r18 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r19, r0 \n\t" \
+ "st z+, r19 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r21, r0 \n\t" \
+ "st z+, r21 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r22, r0 \n\t" \
+ "st z+, r22 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r23, r0 \n\t" \
+ "st z+, r23 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r24, r0 \n\t" \
+ "st z+, r24 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "bst r28, 0 \n\t" \
+ "lsr r29 \n\t" \
+ "ror r28 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r10, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r10, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r11, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r10, r1 \n\t" \
+ "adc r11, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r12, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r10, r0 \n\t" \
+ "adc r11, r1 \n\t" \
+ "adc r12, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r13, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r11, r0 \n\t" \
+ "adc r12, r1 \n\t" \
+ "adc r13, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r14, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r12, r0 \n\t" \
+ "adc r13, r1 \n\t" \
+ "adc r14, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r15, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r13, r0 \n\t" \
+ "adc r14, r1 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r14, r0 \n\t" \
+ "adc r15, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r17, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r15, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r18, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r19, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "mov r21, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "mov r22, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "mov r23, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r21, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "mov r24, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "lsl r28 \n\t" \
+ "bld r28, 0 \n\t" \
+ "rol r29 \n\t" \
+ "rol r10 \n\t" \
+ "rol r11 \n\t" \
+ "rol r12 \n\t" \
+ "rol r13 \n\t" \
+ "rol r14 \n\t" \
+ "rol r15 \n\t" \
+ "rol r16 \n\t" \
+ "rol r17 \n\t" \
+ "rol r18 \n\t" \
+ "rol r19 \n\t" \
+ "rol r21 \n\t" \
+ "rol r22 \n\t" \
+ "rol r23 \n\t" \
+ "rol r24 \n\t" \
+ "ld r0, z \n\t" \
+ "add r28, r0 \n\t" \
+ "st z+, r28 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r29, r0 \n\t" \
+ "st z+, r29 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r10, r0 \n\t" \
+ "st z+, r10 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r11, r0 \n\t" \
+ "st z+, r11 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r12, r0 \n\t" \
+ "st z+, r12 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r13, r0 \n\t" \
+ "st z+, r13 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r14, r0 \n\t" \
+ "st z+, r14 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r15, r0 \n\t" \
+ "st z+, r15 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r16, r0 \n\t" \
+ "st z+, r16 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r17, r0 \n\t" \
+ "st z+, r17 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r18, r0 \n\t" \
+ "st z+, r18 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r19, r0 \n\t" \
+ "st z+, r19 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r21, r0 \n\t" \
+ "st z+, r21 \n\t" \
+ "ld r0, z \n\t" \
+ "adc r22, r0 \n\t" \
+ "st z+, r22 \n\t" \
+ "adc r23, r25 \n\t" \
+ "adc r24, r25 \n\t" \
+ \
+ "mul r2, r2 \n\t" \
+ "mov r28, r0 \n\t" \
+ "mov r29, r1 \n\t" \
+ "mul r3, r3 \n\t" \
+ "mov r10, r0 \n\t" \
+ "mov r11, r1 \n\t" \
+ "mul r4, r4 \n\t" \
+ "mov r12, r0 \n\t" \
+ "mov r13, r1 \n\t" \
+ "mul r5, r5 \n\t" \
+ "mov r14, r0 \n\t" \
+ "mov r15, r1 \n\t" \
+ "add r28, r23 \n\t" \
+ "adc r29, r24 \n\t" \
+ "adc r10, r25 \n\t" \
+ "adc r11, r25 \n\t" \
+ \
+ "mul r7, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mov r16, r25 \n\t" \
+ "mul r8, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mul r9, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r16, r25 \n\t" \
+ "mov r17, r25 \n\t" \
+ "mul r8, r5 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r9, r4 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r16, r1 \n\t" \
+ "adc r17, r25 \n\t" \
+ "mov r18, r25 \n\t" \
+ "mul r9, r5 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r16, r0 \n\t" \
+ "adc r17, r1 \n\t" \
+ "adc r18, r25 \n\t" \
+ "mov r19, r25 \n\t" \
+ "mul r2, r5 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r17, r0 \n\t" \
+ "adc r18, r1 \n\t" \
+ "adc r19, r25 \n\t" \
+ "mov r21, r25 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r18, r0 \n\t" \
+ "adc r19, r1 \n\t" \
+ "adc r21, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r19, r0 \n\t" \
+ "adc r21, r1 \n\t" \
+ \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r16 \n\t" \
+ "rol r17 \n\t" \
+ "rol r18 \n\t" \
+ "rol r19 \n\t" \
+ "rol r21 \n\t" \
+ "adc r15, r25 \n\t" \
+ "add r28, r23 \n\t" \
+ "adc r29, r24 \n\t" \
+ "adc r10, r16 \n\t" \
+ "adc r11, r17 \n\t" \
+ "adc r12, r18 \n\t" \
+ "adc r13, r19 \n\t" \
+ "adc r14, r21 \n\t" \
+ "adc r15, r25 \n\t" \
+ \
+ "st z+, r28 \n\t" \
+ "st z+, r29 \n\t" \
+ "st z+, r10 \n\t" \
+ "st z+, r11 \n\t" \
+ "st z+, r12 \n\t" \
+ "st z+, r13 \n\t" \
+ "st z+, r14 \n\t" \
+ "st z+, r15 \n\t" \
+ "adiw r26, 4 \n\t"
+
+#define FAST_SQUARE_ASM_32 \
+ "ldi r25, 0 \n\t" \
+ "movw r28, r26 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "adiw r28, 20 \n\t" \
+ "ld r12, y+ \n\t" \
+ "ld r13, y+ \n\t" \
+ "ld r14, y+ \n\t" \
+ "ld r15, y+ \n\t" \
+ "ld r16, y+ \n\t" \
+ "ld r17, y+ \n\t" \
+ "adiw r30, 20 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul 2, 12 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r12, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r13, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r14, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r15, y+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r16, y+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r17, y+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r13 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r2, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r24, 0 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r2, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r24, r0 \n\t" \
+ "adc r22, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r24 \n\t" \
+ \
+ "mul r7, r17 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "st z+, r22 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "sbiw r26, 12 \n\t" \
+ "sbiw r30, 44 \n\t" \
+ "ld r2, x+ \n\t" \
+ "ld r3, x+ \n\t" \
+ "ld r4, x+ \n\t" \
+ "ld r5, x+ \n\t" \
+ "ld r6, x+ \n\t" \
+ "ld r7, x+ \n\t" \
+ "ld r8, x+ \n\t" \
+ "ld r9, x+ \n\t" \
+ "ld r10, x+ \n\t" \
+ "ld r11, x+ \n\t" \
+ "ld r12, x+ \n\t" \
+ "ld r13, x+ \n\t" \
+ "ld r14, x+ \n\t" \
+ "ld r15, x+ \n\t" \
+ "ld r16, x+ \n\t" \
+ "ld r17, x+ \n\t" \
+ "ld r18, x+ \n\t" \
+ "ld r19, x+ \n\t" \
+ "ld r20, x+ \n\t" \
+ "ld r21, x+ \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r2, r2 \n\t" \
+ "st z+, r0 \n\t" \
+ "mov r22, r1 \n\t" \
+ \
+ "ldi r24, 0 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "add r22, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r24, r25 \n\t" \
+ "st z+, r22 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r10 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r6, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r11 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r12 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r7, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r14 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r8, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r15 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r16 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r9, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r17 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r18 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r10, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r19 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r2, r20 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r3, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r11, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r2, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r21 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r12, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r3, r2 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r4, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r3, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r4, r2 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r5, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r13, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r4, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r5, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r4, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r3 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r6, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r14, r14 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r5, r4 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r6, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r5, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r6, r4 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r7, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r15, r15 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r6, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r7, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r6, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r5 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r8, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r16, r16 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r7, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r8, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r7, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r8, r6 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r9, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r10, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r17, r17 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r8, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r9, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r8, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r7 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r10, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r11, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r18, r18 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r9, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r10, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r11, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r9, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r10, r8 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r11, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r12, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r19, r19 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r10, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r11, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r12, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r10, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r11, r9 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r12, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r13, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r20, r20 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r11, r10 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r12, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r13, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r11, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r12, r10 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r13, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r14, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r21, r21 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r12, r11 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r13, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r14, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r12, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r13, r11 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r14, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r15, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r2, r2 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r13, r12 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r14, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r15, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ld r13, x+ \n\t" \
+ "ldi r22, 0 \n\t" \
+ "mul r14, r12 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r15, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r16, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r25 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r3, r3 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r14, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r15, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r16, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r17, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "ld r0, z \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r25 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r15, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r16, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r17, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r18, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r4, r4 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r16, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r17, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r18, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r19, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r17, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r18, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r19, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r20, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r5, r5 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r18, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r19, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r20, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r21, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r19, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r20, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r21, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r2, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r6, r6 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r20, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r21, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r2, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r3, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r21, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r2, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r3, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r4, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r7, r7 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r2, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r3, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r4, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r5, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r3, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r4, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r5, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r6, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r8, r8 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r4, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r5, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r6, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r7, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r5, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r6, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r7, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r8, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r9, r9 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r6, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r7, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r8, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r9, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r7, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r8, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "mul r9, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r10, r10 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r8, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r9, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "mul r10, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r22, 0 \n\t" \
+ "mul r9, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r24, r1 \n\t" \
+ "mul r10, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r24 \n\t" \
+ "rol r22 \n\t" \
+ "mul r11, r11 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r24, r1 \n\t" \
+ "adc r22, r25 \n\t" \
+ "add r23, r28 \n\t" \
+ "adc r24, r29 \n\t" \
+ "adc r22, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r29, 0 \n\t" \
+ "mul r10, r13 \n\t" \
+ "mov r23, r0 \n\t" \
+ "mov r28, r1 \n\t" \
+ "mul r11, r12 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "adc r29, r25 \n\t" \
+ "lsl r23 \n\t" \
+ "rol r28 \n\t" \
+ "rol r29 \n\t" \
+ "add r23, r24 \n\t" \
+ "adc r28, r22 \n\t" \
+ "adc r29, r25 \n\t" \
+ "st z+, r23 \n\t" \
+ \
+ "ldi r23, 0 \n\t" \
+ "mul r11, r13 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "mul r12, r12 \n\t" \
+ "add r28, r0 \n\t" \
+ "adc r29, r1 \n\t" \
+ "adc r23, r25 \n\t" \
+ "st z+, r28 \n\t" \
+ \
+ "ldi r28, 0 \n\t" \
+ "mul r12, r13 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "add r29, r0 \n\t" \
+ "adc r23, r1 \n\t" \
+ "adc r28, r25 \n\t" \
+ "st z+, r29 \n\t" \
+ \
+ "mul r13, r13 \n\t" \
+ "add r23, r0 \n\t" \
+ "adc r28, r1 \n\t" \
+ "st z+, r23 \n\t" \
+ "st z+, r28 \n\t"
+
+#endif /* _UECC_ASM_AVR_MULT_SQUARE_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/curve-specific.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/curve-specific.inc
new file mode 100644
index 00000000..0453b212
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/curve-specific.inc
@@ -0,0 +1,1248 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_CURVE_SPECIFIC_H_
+#define _UECC_CURVE_SPECIFIC_H_
+
+#define num_bytes_secp160r1 20
+#define num_bytes_secp192r1 24
+#define num_bytes_secp224r1 28
+#define num_bytes_secp256r1 32
+#define num_bytes_secp256k1 32
+
+#if (uECC_WORD_SIZE == 1)
+
+#define num_words_secp160r1 20
+#define num_words_secp192r1 24
+#define num_words_secp224r1 28
+#define num_words_secp256r1 32
+#define num_words_secp256k1 32
+
+#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \
+ 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h
+#define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d
+
+#elif (uECC_WORD_SIZE == 4)
+
+#define num_words_secp160r1 5
+#define num_words_secp192r1 6
+#define num_words_secp224r1 7
+#define num_words_secp256r1 8
+#define num_words_secp256k1 8
+
+#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
+#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
+
+#elif (uECC_WORD_SIZE == 8)
+
+#define num_words_secp160r1 3
+#define num_words_secp192r1 3
+#define num_words_secp224r1 4
+#define num_words_secp256r1 4
+#define num_words_secp256k1 4
+
+#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##ull
+#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##ull
+
+#endif /* uECC_WORD_SIZE */
+
+#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
+ uECC_SUPPORTS_secp224r1 || uECC_SUPPORTS_secp256r1
+static void double_jacobian_default(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * Z1,
+ uECC_Curve curve) {
+ /* t1 = X, t2 = Y, t3 = Z */
+ uECC_word_t t4[uECC_MAX_WORDS];
+ uECC_word_t t5[uECC_MAX_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ if (uECC_vli_isZero(Z1, num_words)) {
+ return;
+ }
+
+ uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
+ uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
+ uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
+ uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
+ uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
+
+ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
+ uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
+ uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
+ uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
+
+ uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
+ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
+ if (uECC_vli_testBit(X1, 0)) {
+ uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
+ uECC_vli_rshift1(X1, num_words);
+ X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
+ } else {
+ uECC_vli_rshift1(X1, num_words);
+ }
+ /* t1 = 3/2*(x1^2 - z1^4) = B */
+
+ uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
+ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
+ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
+ uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
+ uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
+ uECC_vli_modSub(t4, X1, t4, curve->p, num_words); /* t4 = B * (A - x3) - y1^4 = y3 */
+
+ uECC_vli_set(X1, Z1, num_words);
+ uECC_vli_set(Z1, Y1, num_words);
+ uECC_vli_set(Y1, t4, num_words);
+}
+
+/* Computes result = x^3 + ax + b. result must not overlap x. */
+static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
+ uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
+ uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
+ uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
+ uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); /* r = x^3 - 3x + b */
+}
+#endif /* uECC_SUPPORTS_secp... */
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
+ uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
+/* Compute a = sqrt(a) (mod curve_p). */
+static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
+ bitcount_t i;
+ uECC_word_t p1[uECC_MAX_WORDS] = {1};
+ uECC_word_t l_result[uECC_MAX_WORDS] = {1};
+ wordcount_t num_words = curve->num_words;
+
+ /* When curve->p == 3 (mod 4), we can compute
+ sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
+ uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
+ for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
+ uECC_vli_modSquare_fast(l_result, l_result, curve);
+ if (uECC_vli_testBit(p1, i)) {
+ uECC_vli_modMult_fast(l_result, l_result, a, curve);
+ }
+ }
+ uECC_vli_set(a, l_result, num_words);
+}
+#endif /* uECC_SUPPORTS_secp... */
+#endif /* uECC_SUPPORT_COMPRESSED_POINT */
+
+#if uECC_SUPPORTS_secp160r1
+
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product);
+#endif
+
+static const struct uECC_Curve_t curve_secp160r1 = {
+ num_words_secp160r1,
+ num_bytes_secp160r1,
+ 161, /* num_n_bits */
+ { BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_4(FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9),
+ BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00) },
+ { BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68),
+ BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E),
+ BYTES_TO_WORDS_4(68, B5, 96, 4A),
+
+ BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04),
+ BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31),
+ BYTES_TO_WORDS_4(55, 28, A6, 23) },
+ { BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81),
+ BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54),
+ BYTES_TO_WORDS_4(FC, BE, 97, 1C) },
+ &double_jacobian_default,
+#if uECC_SUPPORT_COMPRESSED_POINT
+ &mod_sqrt_default,
+#endif
+ &x_side_default,
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ &vli_mmod_fast_secp160r1
+#endif
+};
+
+uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; }
+
+#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1)
+/* Computes result = product % curve_p
+ see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354
+
+ Note that this only works if log2(omega) < log2(p) / 2 */
+static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right);
+#if uECC_WORD_SIZE == 8
+static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
+ uECC_word_t tmp[2 * num_words_secp160r1];
+ uECC_word_t copy;
+
+ uECC_vli_clear(tmp, num_words_secp160r1);
+ uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
+
+ omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */
+
+ product[num_words_secp160r1 - 1] &= 0xffffffff;
+ copy = tmp[num_words_secp160r1 - 1];
+ tmp[num_words_secp160r1 - 1] &= 0xffffffff;
+ uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
+ uECC_vli_clear(product, num_words_secp160r1);
+ tmp[num_words_secp160r1 - 1] = copy;
+ omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */
+ uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
+
+ while (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
+ uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
+ }
+}
+
+static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) {
+ uint32_t carry;
+ unsigned i;
+
+ /* Multiply by (2^31 + 1). */
+ carry = 0;
+ for (i = 0; i < num_words_secp160r1; ++i) {
+ uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32);
+ result[i] = (tmp << 31) + tmp + carry;
+ carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp));
+ }
+ result[i] = carry;
+}
+#else
+static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) {
+ uECC_word_t tmp[2 * num_words_secp160r1];
+ uECC_word_t carry;
+
+ uECC_vli_clear(tmp, num_words_secp160r1);
+ uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
+
+ omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */
+
+ carry = uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */
+ uECC_vli_clear(product, num_words_secp160r1);
+ omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */
+ carry += uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */
+
+ while (carry > 0) {
+ --carry;
+ uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
+ }
+ if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) {
+ uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
+ }
+}
+#endif
+
+#if uECC_WORD_SIZE == 1
+static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) {
+ uint8_t carry;
+ uint8_t i;
+
+ /* Multiply by (2^31 + 1). */
+ uECC_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */
+ uECC_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */
+ result[3] = right[0] << 7; /* get last bit from shift */
+
+ carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
+ for (i = num_words_secp160r1; carry; ++i) {
+ uint16_t sum = (uint16_t)result[i] + carry;
+ result[i] = (uint8_t)sum;
+ carry = sum >> 8;
+ }
+}
+#elif uECC_WORD_SIZE == 4
+static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) {
+ uint32_t carry;
+ unsigned i;
+
+ /* Multiply by (2^31 + 1). */
+ uECC_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */
+ uECC_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */
+ result[0] = right[0] << 31; /* get last bit from shift */
+
+ carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */
+ for (i = num_words_secp160r1; carry; ++i) {
+ uint64_t sum = (uint64_t)result[i] + carry;
+ result[i] = (uint32_t)sum;
+ carry = sum >> 32;
+ }
+}
+#endif /* uECC_WORD_SIZE */
+#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */
+
+#endif /* uECC_SUPPORTS_secp160r1 */
+
+#if uECC_SUPPORTS_secp192r1
+
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product);
+#endif
+
+static const struct uECC_Curve_t curve_secp192r1 = {
+ num_words_secp192r1,
+ num_bytes_secp192r1,
+ 192, /* num_n_bits */
+ { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14),
+ BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4),
+ BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C),
+ BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18),
+
+ BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73),
+ BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63),
+ BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07) },
+ { BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE),
+ BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F),
+ BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64) },
+ &double_jacobian_default,
+#if uECC_SUPPORT_COMPRESSED_POINT
+ &mod_sqrt_default,
+#endif
+ &x_side_default,
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ &vli_mmod_fast_secp192r1
+#endif
+};
+
+uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; }
+
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+/* Computes result = product % curve_p.
+ See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */
+#if uECC_WORD_SIZE == 1
+static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) {
+ uint8_t tmp[num_words_secp192r1];
+ uint8_t carry;
+
+ uECC_vli_set(result, product, num_words_secp192r1);
+
+ uECC_vli_set(tmp, &product[24], num_words_secp192r1);
+ carry = uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
+ tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27];
+ tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
+ tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
+ tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ tmp[0] = tmp[8] = product[40];
+ tmp[1] = tmp[9] = product[41];
+ tmp[2] = tmp[10] = product[42];
+ tmp[3] = tmp[11] = product[43];
+ tmp[4] = tmp[12] = product[44];
+ tmp[5] = tmp[13] = product[45];
+ tmp[6] = tmp[14] = product[46];
+ tmp[7] = tmp[15] = product[47];
+ tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
+ carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
+ }
+}
+#elif uECC_WORD_SIZE == 4
+static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) {
+ uint32_t tmp[num_words_secp192r1];
+ int carry;
+
+ uECC_vli_set(result, product, num_words_secp192r1);
+
+ uECC_vli_set(tmp, &product[6], num_words_secp192r1);
+ carry = uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ tmp[0] = tmp[1] = 0;
+ tmp[2] = product[6];
+ tmp[3] = product[7];
+ tmp[4] = product[8];
+ tmp[5] = product[9];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ tmp[0] = tmp[2] = product[10];
+ tmp[1] = tmp[3] = product[11];
+ tmp[4] = tmp[5] = 0;
+ carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
+ }
+}
+#else
+static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) {
+ uint64_t tmp[num_words_secp192r1];
+ int carry;
+
+ uECC_vli_set(result, product, num_words_secp192r1);
+
+ uECC_vli_set(tmp, &product[3], num_words_secp192r1);
+ carry = (int)uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ tmp[0] = 0;
+ tmp[1] = product[3];
+ tmp[2] = product[4];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ tmp[0] = tmp[1] = product[5];
+ tmp[2] = 0;
+ carry += uECC_vli_add(result, result, tmp, num_words_secp192r1);
+
+ while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
+ }
+}
+#endif /* uECC_WORD_SIZE */
+#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
+
+#endif /* uECC_SUPPORTS_secp192r1 */
+
+#if uECC_SUPPORTS_secp224r1
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve);
+#endif
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product);
+#endif
+
+static const struct uECC_Curve_t curve_secp224r1 = {
+ num_words_secp224r1,
+ num_bytes_secp224r1,
+ 224, /* num_n_bits */
+ { BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_4(FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13),
+ BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_4(FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34),
+ BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A),
+ BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B),
+ BYTES_TO_WORDS_4(BD, 0C, 0E, B7),
+
+ BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44),
+ BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD),
+ BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5),
+ BYTES_TO_WORDS_4(88, 63, 37, BD) },
+ { BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27),
+ BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50),
+ BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C),
+ BYTES_TO_WORDS_4(85, 0A, 05, B4) },
+ &double_jacobian_default,
+#if uECC_SUPPORT_COMPRESSED_POINT
+ &mod_sqrt_secp224r1,
+#endif
+ &x_side_default,
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ &vli_mmod_fast_secp224r1
+#endif
+};
+
+uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; }
+
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+/* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+static void mod_sqrt_secp224r1_rs(uECC_word_t *d1,
+ uECC_word_t *e1,
+ uECC_word_t *f1,
+ const uECC_word_t *d0,
+ const uECC_word_t *e0,
+ const uECC_word_t *f0) {
+ uECC_word_t t[num_words_secp224r1];
+
+ uECC_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */
+ uECC_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */
+ uECC_vli_modAdd(d1, t, f0, curve_secp224r1.p, num_words_secp224r1); /* d1 <-- t + f0 */
+ uECC_vli_modAdd(e1, e1, e1, curve_secp224r1.p, num_words_secp224r1); /* e1 <-- e1 + e1 */
+ uECC_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */
+ uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */
+ uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */
+}
+
+/* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+static void mod_sqrt_secp224r1_rss(uECC_word_t *d1,
+ uECC_word_t *e1,
+ uECC_word_t *f1,
+ const uECC_word_t *d0,
+ const uECC_word_t *e0,
+ const uECC_word_t *f0,
+ const bitcount_t j) {
+ bitcount_t i;
+
+ uECC_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */
+ uECC_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */
+ uECC_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */
+ for (i = 1; i <= j; i++) {
+ mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */
+ }
+}
+
+/* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+static void mod_sqrt_secp224r1_rm(uECC_word_t *d2,
+ uECC_word_t *e2,
+ uECC_word_t *f2,
+ const uECC_word_t *c,
+ const uECC_word_t *d0,
+ const uECC_word_t *e0,
+ const uECC_word_t *d1,
+ const uECC_word_t *e1) {
+ uECC_word_t t1[num_words_secp224r1];
+ uECC_word_t t2[num_words_secp224r1];
+
+ uECC_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */
+ uECC_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */
+ /* t1 <-- p - t1 */
+ uECC_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p, num_words_secp224r1);
+ uECC_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */
+ uECC_vli_modAdd(t2, t2, t1, curve_secp224r1.p, num_words_secp224r1); /* t2 <-- t2 + t1 */
+ uECC_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */
+ uECC_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */
+ uECC_vli_modAdd(e2, e2, t1, curve_secp224r1.p, num_words_secp224r1); /* e2 <-- e2 + t1 */
+ uECC_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */
+ uECC_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */
+ /* f2 <-- p - f2 */
+ uECC_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p, num_words_secp224r1);
+ uECC_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */
+}
+
+/* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+static void mod_sqrt_secp224r1_rp(uECC_word_t *d1,
+ uECC_word_t *e1,
+ uECC_word_t *f1,
+ const uECC_word_t *c,
+ const uECC_word_t *r) {
+ wordcount_t i;
+ wordcount_t pow2i = 1;
+ uECC_word_t d0[num_words_secp224r1];
+ uECC_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */
+ uECC_word_t f0[num_words_secp224r1];
+
+ uECC_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */
+ /* f0 <-- p - c */
+ uECC_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p, num_words_secp224r1);
+ for (i = 0; i <= 6; i++) {
+ mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */
+ mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */
+ uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
+ uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
+ uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
+ pow2i *= 2;
+ }
+}
+
+/* Compute a = sqrt(a) (mod curve_p). */
+/* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) {
+ bitcount_t i;
+ uECC_word_t e1[num_words_secp224r1];
+ uECC_word_t f1[num_words_secp224r1];
+ uECC_word_t d0[num_words_secp224r1];
+ uECC_word_t e0[num_words_secp224r1];
+ uECC_word_t f0[num_words_secp224r1];
+ uECC_word_t d1[num_words_secp224r1];
+
+ /* s = a; using constant instead of random value */
+ mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */
+ mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
+ for (i = 1; i <= 95; i++) {
+ uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
+ uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
+ uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
+ mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */
+ if (uECC_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */
+ break;
+ }
+ }
+ uECC_vli_modInv(f1, e0, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- 1 / e0 */
+ uECC_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */
+}
+#endif /* uECC_SUPPORT_COMPRESSED_POINT */
+
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+/* Computes result = product % curve_p
+ from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+#if uECC_WORD_SIZE == 1
+static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
+ uint8_t tmp[num_words_secp224r1];
+ int8_t carry;
+
+ /* t */
+ uECC_vli_set(result, product, num_words_secp224r1);
+
+ /* s1 */
+ tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+ tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
+ tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
+ tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31];
+ tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35];
+ tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39];
+ tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43];
+ carry = uECC_vli_add(result, result, tmp, num_words_secp224r1);
+
+ /* s2 */
+ tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
+ tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
+ tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
+ tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
+ carry += uECC_vli_add(result, result, tmp, num_words_secp224r1);
+
+ /* d1 */
+ tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31];
+ tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35];
+ tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39];
+ tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43];
+ tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47];
+ tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51];
+ tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
+
+ /* d2 */
+ tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
+ tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
+ tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
+ tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
+ tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
+ tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
+ tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
+ } while (carry < 0);
+ } else {
+ while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
+ }
+ }
+}
+#elif uECC_WORD_SIZE == 4
+static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product)
+{
+ uint32_t tmp[num_words_secp224r1];
+ int carry;
+
+ /* t */
+ uECC_vli_set(result, product, num_words_secp224r1);
+
+ /* s1 */
+ tmp[0] = tmp[1] = tmp[2] = 0;
+ tmp[3] = product[7];
+ tmp[4] = product[8];
+ tmp[5] = product[9];
+ tmp[6] = product[10];
+ carry = uECC_vli_add(result, result, tmp, num_words_secp224r1);
+
+ /* s2 */
+ tmp[3] = product[11];
+ tmp[4] = product[12];
+ tmp[5] = product[13];
+ tmp[6] = 0;
+ carry += uECC_vli_add(result, result, tmp, num_words_secp224r1);
+
+ /* d1 */
+ tmp[0] = product[7];
+ tmp[1] = product[8];
+ tmp[2] = product[9];
+ tmp[3] = product[10];
+ tmp[4] = product[11];
+ tmp[5] = product[12];
+ tmp[6] = product[13];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
+
+ /* d2 */
+ tmp[0] = product[11];
+ tmp[1] = product[12];
+ tmp[2] = product[13];
+ tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0;
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
+ } while (carry < 0);
+ } else {
+ while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
+ }
+ }
+}
+#else
+static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product)
+{
+ uint64_t tmp[num_words_secp224r1];
+ int carry = 0;
+
+ /* t */
+ uECC_vli_set(result, product, num_words_secp224r1);
+ result[num_words_secp224r1 - 1] &= 0xffffffff;
+
+ /* s1 */
+ tmp[0] = 0;
+ tmp[1] = product[3] & 0xffffffff00000000ull;
+ tmp[2] = product[4];
+ tmp[3] = product[5] & 0xffffffff;
+ uECC_vli_add(result, result, tmp, num_words_secp224r1);
+
+ /* s2 */
+ tmp[1] = product[5] & 0xffffffff00000000ull;
+ tmp[2] = product[6];
+ tmp[3] = 0;
+ uECC_vli_add(result, result, tmp, num_words_secp224r1);
+
+ /* d1 */
+ tmp[0] = (product[3] >> 32) | (product[4] << 32);
+ tmp[1] = (product[4] >> 32) | (product[5] << 32);
+ tmp[2] = (product[5] >> 32) | (product[6] << 32);
+ tmp[3] = product[6] >> 32;
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
+
+ /* d2 */
+ tmp[0] = (product[5] >> 32) | (product[6] << 32);
+ tmp[1] = product[6] >> 32;
+ tmp[2] = tmp[3] = 0;
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1);
+ } while (carry < 0);
+ } else {
+ while (uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) {
+ uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
+ }
+ }
+}
+#endif /* uECC_WORD_SIZE */
+#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */
+
+#endif /* uECC_SUPPORTS_secp224r1 */
+
+#if uECC_SUPPORTS_secp256r1
+
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product);
+#endif
+
+static const struct uECC_Curve_t curve_secp256r1 = {
+ num_words_secp256r1,
+ num_bytes_secp256r1,
+ 256, /* num_n_bits */
+ { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
+ BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
+ BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
+ BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
+ BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
+
+ BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
+ BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
+ BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
+ BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) },
+ { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
+ BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
+ BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
+ BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) },
+ &double_jacobian_default,
+#if uECC_SUPPORT_COMPRESSED_POINT
+ &mod_sqrt_default,
+#endif
+ &x_side_default,
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ &vli_mmod_fast_secp256r1
+#endif
+};
+
+uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; }
+
+
+#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1)
+/* Computes result = product % curve_p
+ from http://www.nsa.gov/ia/_files/nist-routines.pdf */
+#if uECC_WORD_SIZE == 1
+static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) {
+ uint8_t tmp[num_words_secp256r1];
+ int8_t carry;
+
+ /* t */
+ uECC_vli_set(result, product, num_words_secp256r1);
+
+ /* s1 */
+ tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+ tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
+ tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
+ tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47];
+ tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51];
+ tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55];
+ tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59];
+ tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63];
+ carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s2 */
+ tmp[12] = product[48]; tmp[13] = product[49]; tmp[14] = product[50]; tmp[15] = product[51];
+ tmp[16] = product[52]; tmp[17] = product[53]; tmp[18] = product[54]; tmp[19] = product[55];
+ tmp[20] = product[56]; tmp[21] = product[57]; tmp[22] = product[58]; tmp[23] = product[59];
+ tmp[24] = product[60]; tmp[25] = product[61]; tmp[26] = product[62]; tmp[27] = product[63];
+ tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0;
+ carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s3 */
+ tmp[0] = product[32]; tmp[1] = product[33]; tmp[2] = product[34]; tmp[3] = product[35];
+ tmp[4] = product[36]; tmp[5] = product[37]; tmp[6] = product[38]; tmp[7] = product[39];
+ tmp[8] = product[40]; tmp[9] = product[41]; tmp[10] = product[42]; tmp[11] = product[43];
+ tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
+ tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
+ tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
+ tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59];
+ tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s4 */
+ tmp[0] = product[36]; tmp[1] = product[37]; tmp[2] = product[38]; tmp[3] = product[39];
+ tmp[4] = product[40]; tmp[5] = product[41]; tmp[6] = product[42]; tmp[7] = product[43];
+ tmp[8] = product[44]; tmp[9] = product[45]; tmp[10] = product[46]; tmp[11] = product[47];
+ tmp[12] = product[52]; tmp[13] = product[53]; tmp[14] = product[54]; tmp[15] = product[55];
+ tmp[16] = product[56]; tmp[17] = product[57]; tmp[18] = product[58]; tmp[19] = product[59];
+ tmp[20] = product[60]; tmp[21] = product[61]; tmp[22] = product[62]; tmp[23] = product[63];
+ tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55];
+ tmp[28] = product[32]; tmp[29] = product[33]; tmp[30] = product[34]; tmp[31] = product[35];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* d1 */
+ tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47];
+ tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51];
+ tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55];
+ tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
+ tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
+ tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
+ tmp[24] = product[32]; tmp[25] = product[33]; tmp[26] = product[34]; tmp[27] = product[35];
+ tmp[28] = product[40]; tmp[29] = product[41]; tmp[30] = product[42]; tmp[31] = product[43];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d2 */
+ tmp[0] = product[48]; tmp[1] = product[49]; tmp[2] = product[50]; tmp[3] = product[51];
+ tmp[4] = product[52]; tmp[5] = product[53]; tmp[6] = product[54]; tmp[7] = product[55];
+ tmp[8] = product[56]; tmp[9] = product[57]; tmp[10] = product[58]; tmp[11] = product[59];
+ tmp[12] = product[60]; tmp[13] = product[61]; tmp[14] = product[62]; tmp[15] = product[63];
+ tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
+ tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
+ tmp[24] = product[36]; tmp[25] = product[37]; tmp[26] = product[38]; tmp[27] = product[39];
+ tmp[28] = product[44]; tmp[29] = product[45]; tmp[30] = product[46]; tmp[31] = product[47];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d3 */
+ tmp[0] = product[52]; tmp[1] = product[53]; tmp[2] = product[54]; tmp[3] = product[55];
+ tmp[4] = product[56]; tmp[5] = product[57]; tmp[6] = product[58]; tmp[7] = product[59];
+ tmp[8] = product[60]; tmp[9] = product[61]; tmp[10] = product[62]; tmp[11] = product[63];
+ tmp[12] = product[32]; tmp[13] = product[33]; tmp[14] = product[34]; tmp[15] = product[35];
+ tmp[16] = product[36]; tmp[17] = product[37]; tmp[18] = product[38]; tmp[19] = product[39];
+ tmp[20] = product[40]; tmp[21] = product[41]; tmp[22] = product[42]; tmp[23] = product[43];
+ tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
+ tmp[28] = product[48]; tmp[29] = product[49]; tmp[30] = product[50]; tmp[31] = product[51];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d4 */
+ tmp[0] = product[56]; tmp[1] = product[57]; tmp[2] = product[58]; tmp[3] = product[59];
+ tmp[4] = product[60]; tmp[5] = product[61]; tmp[6] = product[62]; tmp[7] = product[63];
+ tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
+ tmp[12] = product[36]; tmp[13] = product[37]; tmp[14] = product[38]; tmp[15] = product[39];
+ tmp[16] = product[40]; tmp[17] = product[41]; tmp[18] = product[42]; tmp[19] = product[43];
+ tmp[20] = product[44]; tmp[21] = product[45]; tmp[22] = product[46]; tmp[23] = product[47];
+ tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
+ tmp[28] = product[52]; tmp[29] = product[53]; tmp[30] = product[54]; tmp[31] = product[55];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
+ } while (carry < 0);
+ } else {
+ while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
+ }
+ }
+}
+#elif uECC_WORD_SIZE == 4
+static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) {
+ uint32_t tmp[num_words_secp256r1];
+ int carry;
+
+ /* t */
+ uECC_vli_set(result, product, num_words_secp256r1);
+
+ /* s1 */
+ tmp[0] = tmp[1] = tmp[2] = 0;
+ tmp[3] = product[11];
+ tmp[4] = product[12];
+ tmp[5] = product[13];
+ tmp[6] = product[14];
+ tmp[7] = product[15];
+ carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s2 */
+ tmp[3] = product[12];
+ tmp[4] = product[13];
+ tmp[5] = product[14];
+ tmp[6] = product[15];
+ tmp[7] = 0;
+ carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s3 */
+ tmp[0] = product[8];
+ tmp[1] = product[9];
+ tmp[2] = product[10];
+ tmp[3] = tmp[4] = tmp[5] = 0;
+ tmp[6] = product[14];
+ tmp[7] = product[15];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s4 */
+ tmp[0] = product[9];
+ tmp[1] = product[10];
+ tmp[2] = product[11];
+ tmp[3] = product[13];
+ tmp[4] = product[14];
+ tmp[5] = product[15];
+ tmp[6] = product[13];
+ tmp[7] = product[8];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* d1 */
+ tmp[0] = product[11];
+ tmp[1] = product[12];
+ tmp[2] = product[13];
+ tmp[3] = tmp[4] = tmp[5] = 0;
+ tmp[6] = product[8];
+ tmp[7] = product[10];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d2 */
+ tmp[0] = product[12];
+ tmp[1] = product[13];
+ tmp[2] = product[14];
+ tmp[3] = product[15];
+ tmp[4] = tmp[5] = 0;
+ tmp[6] = product[9];
+ tmp[7] = product[11];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d3 */
+ tmp[0] = product[13];
+ tmp[1] = product[14];
+ tmp[2] = product[15];
+ tmp[3] = product[8];
+ tmp[4] = product[9];
+ tmp[5] = product[10];
+ tmp[6] = 0;
+ tmp[7] = product[12];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d4 */
+ tmp[0] = product[14];
+ tmp[1] = product[15];
+ tmp[2] = 0;
+ tmp[3] = product[9];
+ tmp[4] = product[10];
+ tmp[5] = product[11];
+ tmp[6] = 0;
+ tmp[7] = product[13];
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
+ } while (carry < 0);
+ } else {
+ while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
+ }
+ }
+}
+#else
+static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) {
+ uint64_t tmp[num_words_secp256r1];
+ int carry;
+
+ /* t */
+ uECC_vli_set(result, product, num_words_secp256r1);
+
+ /* s1 */
+ tmp[0] = 0;
+ tmp[1] = product[5] & 0xffffffff00000000ull;
+ tmp[2] = product[6];
+ tmp[3] = product[7];
+ carry = (int)uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s2 */
+ tmp[1] = product[6] << 32;
+ tmp[2] = (product[6] >> 32) | (product[7] << 32);
+ tmp[3] = product[7] >> 32;
+ carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s3 */
+ tmp[0] = product[4];
+ tmp[1] = product[5] & 0xffffffff;
+ tmp[2] = 0;
+ tmp[3] = product[7];
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* s4 */
+ tmp[0] = (product[4] >> 32) | (product[5] << 32);
+ tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
+ tmp[2] = product[7];
+ tmp[3] = (product[6] >> 32) | (product[4] << 32);
+ carry += uECC_vli_add(result, result, tmp, num_words_secp256r1);
+
+ /* d1 */
+ tmp[0] = (product[5] >> 32) | (product[6] << 32);
+ tmp[1] = (product[6] >> 32);
+ tmp[2] = 0;
+ tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d2 */
+ tmp[0] = product[6];
+ tmp[1] = product[7];
+ tmp[2] = 0;
+ tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d3 */
+ tmp[0] = (product[6] >> 32) | (product[7] << 32);
+ tmp[1] = (product[7] >> 32) | (product[4] << 32);
+ tmp[2] = (product[4] >> 32) | (product[5] << 32);
+ tmp[3] = (product[6] << 32);
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ /* d4 */
+ tmp[0] = product[7];
+ tmp[1] = product[4] & 0xffffffff00000000ull;
+ tmp[2] = product[5];
+ tmp[3] = product[6] & 0xffffffff00000000ull;
+ carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1);
+ } while (carry < 0);
+ } else {
+ while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1);
+ }
+ }
+}
+#endif /* uECC_WORD_SIZE */
+#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */
+
+#endif /* uECC_SUPPORTS_secp256r1 */
+
+#if uECC_SUPPORTS_secp256k1
+
+static void double_jacobian_secp256k1(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * Z1,
+ uECC_Curve curve);
+static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product);
+#endif
+
+static const struct uECC_Curve_t curve_secp256k1 = {
+ num_words_secp256k1,
+ num_bytes_secp256k1,
+ 256, /* num_n_bits */
+ { BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF),
+ BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA),
+ BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) },
+ { BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59),
+ BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02),
+ BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55),
+ BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79),
+
+ BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C),
+ BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD),
+ BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D),
+ BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) },
+ { BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) },
+ &double_jacobian_secp256k1,
+#if uECC_SUPPORT_COMPRESSED_POINT
+ &mod_sqrt_default,
+#endif
+ &x_side_secp256k1,
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ &vli_mmod_fast_secp256k1
+#endif
+};
+
+uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; }
+
+
+/* Double in place */
+static void double_jacobian_secp256k1(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * Z1,
+ uECC_Curve curve) {
+ /* t1 = X, t2 = Y, t3 = Z */
+ uECC_word_t t4[num_words_secp256k1];
+ uECC_word_t t5[num_words_secp256k1];
+
+ if (uECC_vli_isZero(Z1, num_words_secp256k1)) {
+ return;
+ }
+
+ uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */
+ uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
+ uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */
+ uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */
+ uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
+
+ uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
+ uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
+ if (uECC_vli_testBit(Y1, 0)) {
+ uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1);
+ uECC_vli_rshift1(Y1, num_words_secp256k1);
+ Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1);
+ } else {
+ uECC_vli_rshift1(Y1, num_words_secp256k1);
+ }
+ /* t2 = 3/2*(x1^2) = B */
+
+ uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */
+ uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */
+ uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
+
+ uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */
+ uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */
+ uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
+}
+
+/* Computes result = x^3 + b. result must not overlap x. */
+static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
+ uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
+ uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */
+ uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */
+}
+
+#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256k1)
+static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right);
+static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) {
+ uECC_word_t tmp[2 * num_words_secp256k1];
+ uECC_word_t carry;
+
+ uECC_vli_clear(tmp, num_words_secp256k1);
+ uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
+
+ omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */
+
+ carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */
+ uECC_vli_clear(product, num_words_secp256k1);
+ omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */
+ carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */
+
+ while (carry > 0) {
+ --carry;
+ uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
+ }
+ if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) {
+ uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
+ }
+}
+
+#if uECC_WORD_SIZE == 1
+static void omega_mult_secp256k1(uint8_t * result, const uint8_t * right) {
+ /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
+ uECC_word_t r0 = 0;
+ uECC_word_t r1 = 0;
+ uECC_word_t r2 = 0;
+ wordcount_t k;
+
+ /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
+ muladd(0xD1, right[0], &r0, &r1, &r2);
+ result[0] = r0;
+ r0 = r1;
+ r1 = r2;
+ /* r2 is still 0 */
+
+ for (k = 1; k < num_words_secp256k1; ++k) {
+ muladd(0x03, right[k - 1], &r0, &r1, &r2);
+ muladd(0xD1, right[k], &r0, &r1, &r2);
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+ muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2);
+ result[num_words_secp256k1] = r0;
+ result[num_words_secp256k1 + 1] = r1;
+ /* add the 2^32 multiple */
+ result[4 + num_words_secp256k1] =
+ uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1);
+}
+#elif uECC_WORD_SIZE == 4
+static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) {
+ /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
+ uint32_t carry = 0;
+ wordcount_t k;
+
+ for (k = 0; k < num_words_secp256k1; ++k) {
+ uint64_t p = (uint64_t)0x3D1 * right[k] + carry;
+ result[k] = (uint32_t) p;
+ carry = p >> 32;
+ }
+ result[num_words_secp256k1] = carry;
+ /* add the 2^32 multiple */
+ result[1 + num_words_secp256k1] =
+ uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1);
+}
+#else
+static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) {
+ uECC_word_t r0 = 0;
+ uECC_word_t r1 = 0;
+ uECC_word_t r2 = 0;
+ wordcount_t k;
+
+ /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
+ for (k = 0; k < num_words_secp256k1; ++k) {
+ muladd(0x1000003D1ull, right[k], &r0, &r1, &r2);
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+ result[num_words_secp256k1] = r0;
+}
+#endif /* uECC_WORD_SIZE */
+#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && && !asm_mmod_fast_secp256k1) */
+
+#endif /* uECC_SUPPORTS_secp256k1 */
+
+#endif /* _UECC_CURVE_SPECIFIC_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_project.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_project.py
new file mode 100644
index 00000000..940fadc2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_project.py
@@ -0,0 +1,127 @@
+import os
+
+c, link, asm, utils = emk.module("c", "link", "asm", "utils")
+
+default_compile_flags = ["-fvisibility=hidden", "-Wall", "-Wextra", "-Wshadow", "-Werror", "-Wno-missing-field-initializers", "-Wno-unused-parameter", \
+ "-Wno-comment", "-Wno-unused", "-Wno-unknown-pragmas"]
+default_link_flags = []
+opt_flags = {"dbg":["-g"], "std":["-O2"], "max":["-O3"], "small":["-Os"]}
+opt_link_flags = {"dbg":[], "std":[], "max":[], "small":[]}
+c_flags = ["-std=c99"]
+cxx_flags = ["-std=c++11", "-Wno-reorder", "-fno-rtti", "-fno-exceptions"]
+c_link_flags = []
+cxx_link_flags = ["-fno-rtti", "-fno-exceptions"]
+
+def setup_build_dir():
+ build_arch = None
+ if "arch" in emk.options:
+ build_arch = emk.options["arch"]
+ elif not emk.cleaning:
+ build_arch = "osx"
+ emk.options["arch"] = build_arch
+
+ opt_level = None
+ if "opt" in emk.options:
+ level = emk.options["opt"]
+ if level in opt_flags:
+ opt_level = level
+ else:
+ emk.log.warning("Unknown optimization level '%s'" % (level))
+ elif not emk.cleaning:
+ opt_level = "dbg"
+ emk.options["opt"] = opt_level
+
+ dirs = ["__build__"]
+ if build_arch:
+ dirs.append(build_arch)
+ if opt_level:
+ dirs.append(opt_level)
+ emk.build_dir = os.path.join(*dirs)
+
+def setup_osx():
+ global c
+ global link
+
+ flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof"]
+ c.flags.extend(flags)
+ c.cxx.flags += ["-stdlib=libc++"]
+ link.cxx.flags += ["-stdlib=libc++"]
+
+ link_flags = [("-arch", "x86_64")]
+ link.local_flags.extend(link_flags)
+
+def setup_avr():
+ global c
+ global link
+
+ c.compiler = c.GccCompiler("/Projects/avr-tools/bin/avr-")
+ c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"]
+ link.linker = link.GccLinker("/Projects/avr-tools/bin/avr-")
+ link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"]
+ link.strip = True
+
+def setup_arm_thumb():
+ global c
+ global link
+ global asm
+ global utils
+
+ asm.assembler = asm.GccAssembler("/cross/arm_cortex/bin/arm-none-eabi-")
+ c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-")
+ link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-")
+
+ c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"])
+ c.defines["LPC11XX"] = 1
+
+ link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"])
+ link.local_flags.extend(["-Tflash.lds", "-L/Projects/lpc11xx/core", "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"])
+ link.local_syslibs += ["gcc"]
+ link.depdirs += ["/Projects/lpc11xx/stdlib"]
+
+ def do_objcopy(produces, requires):
+ utils.call("/cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0])
+
+ def handle_exe(path):
+ emk.depend(path, "/Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o")
+ emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True)
+ emk.autobuild(path + ".bin")
+
+ link.exe_funcs.append(handle_exe)
+ link.strip = True
+
+ emk.recurse("/Projects/lpc11xx/core")
+
+def setup_linux_rpi():
+ global c
+ global link
+
+ c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
+ link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-")
+
+ c.flags.extend(["-fomit-frame-pointer"])
+
+setup_build_dir()
+
+setup_funcs = {"osx":setup_osx, "avr":setup_avr, "arm_thumb":setup_arm_thumb, "rpi": setup_linux_rpi}
+
+if not emk.cleaning:
+ build_arch = emk.options["arch"]
+ opt_level = emk.options["opt"]
+
+ c.flags.extend(default_compile_flags)
+ c.flags.extend(opt_flags[opt_level])
+ c.c.flags.extend(c_flags)
+ c.cxx.flags.extend(cxx_flags)
+ link.local_flags.extend(default_link_flags)
+ link.local_flags.extend(opt_link_flags[opt_level])
+ link.c.local_flags.extend(c_link_flags)
+ link.cxx.local_flags.extend(cxx_link_flags)
+
+ c.include_dirs.append("$:proj:$")
+
+ if build_arch in setup_funcs:
+ setup_funcs[build_arch]()
+ else:
+ raise emk.BuildError("Unknown target arch '%s'" % (build_arch))
+
+ c.defines["TARGET_ARCH_" + build_arch.upper()] = 1
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_rules.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_rules.py
new file mode 100644
index 00000000..b1d76c81
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/emk_rules.py
@@ -0,0 +1,3 @@
+c, link = emk.module("c", "link")
+
+emk.subdir("test")
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/platform-specific.inc b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/platform-specific.inc
new file mode 100644
index 00000000..1bb595ad
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/platform-specific.inc
@@ -0,0 +1,67 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_PLATFORM_SPECIFIC_H_
+#define _UECC_PLATFORM_SPECIFIC_H_
+
+#include "types.h"
+
+#if (defined(_WIN32) || defined(_WIN64))
+/* Windows */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <wincrypt.h>
+
+static int default_RNG(uint8_t *dest, unsigned size) {
+ HCRYPTPROV prov;
+ if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+ return 0;
+ }
+
+ CryptGenRandom(prov, size, (BYTE *)dest);
+ CryptReleaseContext(prov, 0);
+ return 1;
+}
+#define default_RNG_defined 1
+
+#elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \
+ (defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX)
+
+/* Some POSIX-like system with /dev/urandom or /dev/random. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef O_CLOEXEC
+ #define O_CLOEXEC 0
+#endif
+
+static int default_RNG(uint8_t *dest, unsigned size) {
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ return 0;
+ }
+ }
+
+ char *ptr = (char *)dest;
+ size_t left = size;
+ while (left > 0) {
+ ssize_t bytes_read = read(fd, ptr, left);
+ if (bytes_read <= 0) { // read failed
+ close(fd);
+ return 0;
+ }
+ left -= bytes_read;
+ ptr += bytes_read;
+ }
+
+ close(fd);
+ return 1;
+}
+#define default_RNG_defined 1
+
+#endif /* platform */
+
+#endif /* _UECC_PLATFORM_SPECIFIC_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py
new file mode 100755
index 00000000..402ace19
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_arm.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+
+import sys
+
+if len(sys.argv) < 2:
+ print "Provide the integer size in 32-bit words"
+ sys.exit(1)
+
+size = int(sys.argv[1])
+
+full_rows = size // 3
+init_size = size % 3
+
+if init_size == 0:
+ full_rows = full_rows - 1
+ init_size = 3
+
+def emit(line, *args):
+ s = '"' + line + r' \n\t"'
+ print s % args
+
+rx = [3, 4, 5]
+ry = [6, 7, 8]
+
+#### set up registers
+emit("add r0, %s", (size - init_size) * 4) # move z
+emit("add r2, %s", (size - init_size) * 4) # move y
+
+emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size)]))
+emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(init_size)]))
+
+print ""
+if init_size == 1:
+ emit("umull r9, r10, r3, r6")
+ emit("stmia r0!, {r9, r10}")
+else:
+ #### first two multiplications of initial block
+ emit("umull r11, r12, r3, r6")
+ emit("stmia r0!, {r11}")
+ print ""
+ emit("mov r10, #0")
+ emit("umull r11, r9, r3, r7")
+ emit("adds r12, r12, r11")
+ emit("adc r9, r9, #0")
+ emit("umull r11, r14, r4, r6")
+ emit("adds r12, r12, r11")
+ emit("adcs r9, r9, r14")
+ emit("adc r10, r10, #0")
+ emit("stmia r0!, {r12}")
+ print ""
+
+ #### rest of initial block, with moving accumulator registers
+ acc = [9, 10, 11, 12, 14]
+ if init_size == 3:
+ emit("mov r%s, #0", acc[2])
+ for i in xrange(0, 3):
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ emit("mov r%s, #0", acc[2])
+ for i in xrange(0, 2):
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i + 1], ry[2 - i])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[init_size-1], ry[init_size-1])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("stmia r0!, {r%s}", acc[0])
+ emit("stmia r0!, {r%s}", acc[1])
+print ""
+
+#### reset y and z pointers
+emit("sub r0, %s", (2 * init_size + 3) * 4)
+emit("sub r2, %s", (init_size + 3) * 4)
+
+#### load y registers
+emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(3)]))
+
+#### load additional x registers
+if init_size != 3:
+ emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size, 3)]))
+print ""
+
+prev_size = init_size
+for row in xrange(full_rows):
+ emit("umull r11, r12, r3, r6")
+ emit("stmia r0!, {r11}")
+ print ""
+ emit("mov r10, #0")
+ emit("umull r11, r9, r3, r7")
+ emit("adds r12, r12, r11")
+ emit("adc r9, r9, #0")
+ emit("umull r11, r14, r4, r6")
+ emit("adds r12, r12, r11")
+ emit("adcs r9, r9, r14")
+ emit("adc r10, r10, #0")
+ emit("stmia r0!, {r12}")
+ print ""
+
+ acc = [9, 10, 11, 12, 14]
+ emit("mov r%s, #0", acc[2])
+ for i in xrange(0, 3):
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ #### now we need to start shifting x and loading from z
+ x_regs = [3, 4, 5]
+ for r in xrange(0, prev_size):
+ x_regs = x_regs[1:] + x_regs[:1]
+ emit("ldmia r1!, {r%s}", x_regs[2])
+ emit("mov r%s, #0", acc[2])
+ for i in xrange(0, 3):
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], ry[2 - i])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, #0", acc[1], acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ # done shifting x, start shifting y
+ y_regs = [6, 7, 8]
+ for r in xrange(0, prev_size):
+ y_regs = y_regs[1:] + y_regs[:1]
+ emit("ldmia r2!, {r%s}", y_regs[2])
+ emit("mov r%s, #0", acc[2])
+ for i in xrange(0, 3):
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], y_regs[2 - i])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, #0", acc[1], acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ # done both shifts, do remaining corner
+ emit("mov r%s, #0", acc[2])
+ for i in xrange(0, 2):
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i + 1], y_regs[2 - i])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[2], y_regs[2])
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3])
+ emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4])
+ emit("stmia r0!, {r%s}", acc[0])
+ emit("stmia r0!, {r%s}", acc[1])
+ print ""
+
+ prev_size = prev_size + 3
+ if row < full_rows - 1:
+ #### reset x, y and z pointers
+ emit("sub r0, %s", (2 * prev_size + 3) * 4)
+ emit("sub r1, %s", prev_size * 4)
+ emit("sub r2, %s", (prev_size + 3) * 4)
+
+ #### load x and y registers
+ emit("ldmia r1!, {%s}", ",".join(["r%s" % (rx[i]) for i in xrange(3)]))
+ emit("ldmia r2!, {%s}", ",".join(["r%s" % (ry[i]) for i in xrange(3)]))
+
+ print ""
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py
new file mode 100755
index 00000000..d40e4c23
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+
+import sys
+
+if len(sys.argv) < 2:
+ print "Provide the integer size in bytes"
+ sys.exit(1)
+
+size = int(sys.argv[1])
+
+full_rows = size // 10
+init_size = size % 10
+
+if init_size == 0:
+ full_rows = full_rows - 1
+ init_size = 10
+
+def rx(i):
+ return i + 2
+
+def ry(i):
+ return i + 12
+
+def emit(line, *args):
+ s = '"' + line + r' \n\t"'
+ print s % args
+
+#### set up registers
+emit("adiw r30, %s", size - init_size) # move z
+emit("adiw r28, %s", size - init_size) # move y
+
+for i in xrange(init_size):
+ emit("ld r%s, x+", rx(i))
+for i in xrange(init_size):
+ emit("ld r%s, y+", ry(i))
+
+emit("ldi r25, 0")
+print ""
+if init_size == 1:
+ emit("mul r2, r12")
+ emit("st z+, r0")
+ emit("st z+, r1")
+else:
+ #### first two multiplications of initial block
+ emit("ldi r23, 0")
+ emit("mul r2, r12")
+ emit("st z+, r0")
+ emit("mov r22, r1")
+ print ""
+ emit("ldi r24, 0")
+ emit("mul r2, r13")
+ emit("add r22, r0")
+ emit("adc r23, r1")
+ emit("mul r3, r12")
+ emit("add r22, r0")
+ emit("adc r23, r1")
+ emit("adc r24, r25")
+ emit("st z+, r22")
+ print ""
+
+ #### rest of initial block, with moving accumulator registers
+ acc = [23, 24, 22]
+ for r in xrange(2, init_size):
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, r+1):
+ emit("mul r%s, r%s", rx(i), ry(r - i))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+ for r in xrange(1, init_size-1):
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, init_size-r):
+ emit("mul r%s, r%s", rx(r+i), ry((init_size-1) - i))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+ emit("mul r%s, r%s", rx(init_size-1), ry(init_size-1))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("st z+, r%s", acc[0])
+ emit("st z+, r%s", acc[1])
+print ""
+
+#### reset y and z pointers
+emit("sbiw r30, %s", 2 * init_size + 10)
+emit("sbiw r28, %s", init_size + 10)
+
+#### load y registers
+for i in xrange(10):
+ emit("ld r%s, y+", ry(i))
+
+#### load additional x registers
+for i in xrange(init_size, 10):
+ emit("ld r%s, x+", rx(i))
+print ""
+
+prev_size = init_size
+for row in xrange(full_rows):
+ #### do x = 0-9, y = 0-9 multiplications
+ emit("ldi r23, 0")
+ emit("mul r2, r12")
+ emit("st z+, r0")
+ emit("mov r22, r1")
+ print ""
+ emit("ldi r24, 0")
+ emit("mul r2, r13")
+ emit("add r22, r0")
+ emit("adc r23, r1")
+ emit("mul r3, r12")
+ emit("add r22, r0")
+ emit("adc r23, r1")
+ emit("adc r24, r25")
+ emit("st z+, r22")
+ print ""
+
+ acc = [23, 24, 22]
+ for r in xrange(2, 10):
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, r+1):
+ emit("mul r%s, r%s", rx(i), ry(r - i))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ #### now we need to start shifting x and loading from z
+ x_regs = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
+ for r in xrange(0, prev_size):
+ x_regs = x_regs[1:] + x_regs[:1]
+ emit("ld r%s, x+", x_regs[9]) # load next byte of left
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, 10):
+ emit("mul r%s, r%s", x_regs[i], ry(9 - i))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment)
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r25", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("st z+, r%s", acc[0]) # store next byte (z increments)
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ # done shifting x, start shifting y
+ y_regs = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
+ for r in xrange(0, prev_size):
+ y_regs = y_regs[1:] + y_regs[:1]
+ emit("ld r%s, y+", y_regs[9]) # load next byte of right
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, 10):
+ emit("mul r%s, r%s", x_regs[i], y_regs[9 -i])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment)
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r25", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("st z+, r%s", acc[0]) # store next byte (z increments)
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ # done both shifts, do remaining corner
+ for r in xrange(1, 9):
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, 10-r):
+ emit("mul r%s, r%s", x_regs[r+i], y_regs[9 - i])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, r25", acc[2])
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+ emit("mul r%s, r%s", x_regs[9], y_regs[9])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("st z+, r%s", acc[0])
+ emit("st z+, r%s", acc[1])
+ print ""
+
+ prev_size = prev_size + 10
+ if row < full_rows - 1:
+ #### reset x, y and z pointers
+ emit("sbiw r30, %s", 2 * prev_size + 10)
+ emit("sbiw r28, %s", prev_size + 10)
+ emit("sbiw r26, %s", prev_size)
+
+ #### load x and y registers
+ for i in xrange(10):
+ emit("ld r%s, x+", rx(i))
+ emit("ld r%s, y+", ry(i))
+ print ""
+
+emit("eor r1, r1")
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py
new file mode 100755
index 00000000..f6e654f6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/mult_avr_extra.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python
+
+import sys
+
+if len(sys.argv) < 2:
+ print "Provide the integer size in bytes"
+ sys.exit(1)
+
+size = int(sys.argv[1])
+
+def lhi(i):
+ return i + 2
+
+def rhi(i):
+ return i + 6
+
+left_lo = [10, 11, 12, 13]
+right_lo = [14, 15, 16, 17]
+
+def llo(i):
+ return left_lo[i]
+
+def rlo(i):
+ return right_lo[i]
+
+def emit(line, *args):
+ s = '"' + line + r' \n\t"'
+ print s % args
+
+def update_low():
+ global left_lo
+ global right_lo
+ left_lo = left_lo[1:] + left_lo[:1]
+ right_lo = right_lo[1:] + right_lo[:1]
+ emit("ld r%s, x+", left_lo[3])
+ emit("ld r%s, y+", right_lo[3])
+
+accum = [19, 20, 21]
+
+def acc(i):
+ return accum[i]
+
+def rotate_acc():
+ global accum
+ accum = accum[1:] + accum[:1]
+
+# Load high values
+for i in xrange(4):
+ emit("ld r%s, x+", lhi(i))
+ emit("ld r%s, y+", rhi(i))
+
+emit("sbiw r26, %s", size + 4)
+emit("sbiw r28, %s", size + 4)
+emit("sbiw r30, %s", size)
+
+# Load low values
+for i in xrange(4):
+ emit("ld r%s, x+", llo(i))
+ emit("ld r%s, y+", rlo(i))
+print ""
+
+# Compute initial triangles
+emit("mul r%s, r%s", lhi(0), rlo(0))
+emit("mov r%s, r0", acc(0))
+emit("mov r%s, r1", acc(1))
+emit("ldi r%s, 0", acc(2))
+emit("ld r0, z")
+emit("add r%s, r0", acc(0))
+emit("adc r%s, r25", acc(1))
+emit("mul r%s, r%s", rhi(0), llo(0))
+emit("add r%s, r0", acc(0))
+emit("adc r%s, r1", acc(1))
+emit("adc r%s, r25", acc(2))
+emit("st z+, r%s", acc(0))
+print ""
+rotate_acc()
+
+for i in xrange(1, 4):
+ emit("ldi r%s, 0", acc(2))
+ emit("ld r0, z")
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r25", acc(1))
+ for j in xrange(i + 1):
+ emit("mul r%s, r%s", lhi(j), rlo(i-j))
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r1", acc(1))
+ emit("adc r%s, r25", acc(2))
+ emit("mul r%s, r%s", rhi(j), llo(i-j))
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r1", acc(1))
+ emit("adc r%s, r25", acc(2))
+ emit("st z+, r%s", acc(0))
+ print ""
+ rotate_acc()
+
+# Compute rows overlapping old block
+for i in xrange(4, size):
+ emit("ldi r%s, 0", acc(2))
+ emit("ld r0, z")
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r25", acc(1))
+ update_low()
+ for j in xrange(4):
+ emit("mul r%s, r%s", lhi(j), rlo(3-j))
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r1", acc(1))
+ emit("adc r%s, r25", acc(2))
+ emit("mul r%s, r%s", rhi(j), llo(3-j))
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r1", acc(1))
+ emit("adc r%s, r25", acc(2))
+ emit("st z+, r%s", acc(0))
+ print ""
+ rotate_acc()
+
+# Compute new triangle
+left_combined = [llo(1), llo(2), llo(3), lhi(0), lhi(1), lhi(2), lhi(3)]
+right_combined = [rlo(1), rlo(2), rlo(3), rhi(0), rhi(1), rhi(2), rhi(3)]
+
+def left(i):
+ return left_combined[i]
+
+def right(i):
+ return right_combined[i]
+
+for i in xrange(6):
+ emit("ldi r%s, 0", acc(2))
+ for j in xrange(7 - i):
+ emit("mul r%s, r%s", left(i+j), right(6-j))
+ emit("add r%s, r0", acc(0))
+ emit("adc r%s, r1", acc(1))
+ emit("adc r%s, r25", acc(2))
+ emit("st z+, r%s", acc(0))
+ print ""
+ rotate_acc()
+
+emit("mul r%s, r%s", left(6), right(6))
+emit("add r%s, r0", acc(0))
+emit("adc r%s, r1", acc(1))
+emit("st z+, r%s", acc(0))
+emit("st z+, r%s", acc(1))
+emit("adiw r26, 4")
+emit("adiw r28, 4")
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py
new file mode 100755
index 00000000..5330c7e6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_arm.py
@@ -0,0 +1,242 @@
+#!/usr/bin/env python
+
+import sys
+
+if len(sys.argv) < 2:
+ print "Provide the integer size in 32-bit words"
+ sys.exit(1)
+
+size = int(sys.argv[1])
+
+if size > 8:
+ print "This script doesn't work with integer size %s due to laziness" % (size)
+ sys.exit(1)
+
+init_size = 0
+if size > 6:
+ init_size = size - 6
+
+def emit(line, *args):
+ s = '"' + line + r' \n\t"'
+ print s % args
+
+def mulacc(acc, r1, r2):
+ if size <= 6:
+ emit("umull r1, r14, r%s, r%s", r1, r2)
+ emit("adds r%s, r%s, r1", acc[0], acc[0])
+ emit("adcs r%s, r%s, r14", acc[1], acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+ else:
+ emit("mov r14, r%s", acc[1])
+ emit("umlal r%s, r%s, r%s, r%s", acc[0], acc[1], r1, r2)
+ emit("cmp r14, r%s", acc[1])
+ emit("it hi")
+ emit("adchi r%s, r%s, #0", acc[2], acc[2])
+
+r = [2, 3, 4, 5, 6, 7]
+
+s = size - init_size
+
+if init_size == 1:
+ emit("ldmia r1!, {r2}")
+ emit("add r1, %s", (size - init_size * 2) * 4)
+ emit("ldmia r1!, {r5}")
+
+ emit("add r0, %s", (size - init_size) * 4)
+ emit("umull r8, r9, r2, r5")
+ emit("stmia r0!, {r8, r9}")
+
+ emit("sub r0, %s", (size + init_size) * 4)
+ emit("sub r1, %s", (size) * 4)
+ print ""
+elif init_size == 2:
+ emit("ldmia r1!, {r2, r3}")
+ emit("add r1, %s", (size - init_size * 2) * 4)
+ emit("ldmia r1!, {r5, r6}")
+
+ emit("add r0, %s", (size - init_size) * 4)
+ print ""
+
+ emit("umull r8, r9, r2, r5")
+ emit("stmia r0!, {r8}")
+ print ""
+
+ emit("umull r12, r10, r2, r6")
+ emit("adds r9, r9, r12")
+ emit("adc r10, r10, #0")
+ emit("stmia r0!, {r9}")
+ print ""
+
+ emit("umull r8, r9, r3, r6")
+ emit("adds r10, r10, r8")
+ emit("adc r11, r9, #0")
+ emit("stmia r0!, {r10, r11}")
+ print ""
+
+ emit("sub r0, %s", (size + init_size) * 4)
+ emit("sub r1, %s", (size) * 4)
+
+# load input words
+emit("ldmia r1!, {%s}", ", ".join(["r%s" % (r[i]) for i in xrange(s)]))
+print ""
+
+emit("umull r11, r12, r2, r2")
+emit("stmia r0!, {r11}")
+print ""
+emit("mov r9, #0")
+emit("umull r10, r11, r2, r3")
+emit("adds r12, r12, r10")
+emit("adcs r8, r11, #0")
+emit("adc r9, r9, #0")
+emit("adds r12, r12, r10")
+emit("adcs r8, r8, r11")
+emit("adc r9, r9, #0")
+emit("stmia r0!, {r12}")
+print ""
+emit("mov r10, #0")
+emit("umull r11, r12, r2, r4")
+emit("adds r11, r11, r11")
+emit("adcs r12, r12, r12")
+emit("adc r10, r10, #0")
+emit("adds r8, r8, r11")
+emit("adcs r9, r9, r12")
+emit("adc r10, r10, #0")
+emit("umull r11, r12, r3, r3")
+emit("adds r8, r8, r11")
+emit("adcs r9, r9, r12")
+emit("adc r10, r10, #0")
+emit("stmia r0!, {r8}")
+print ""
+
+acc = [8, 9, 10]
+old_acc = [11, 12]
+for i in xrange(3, s):
+ emit("mov r%s, #0", old_acc[1])
+ tmp = [acc[1], acc[2]]
+ acc = [acc[0], old_acc[0], old_acc[1]]
+ old_acc = tmp
+
+ # gather non-equal words
+ emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], r[0], r[i])
+ for j in xrange(1, (i+1)//2):
+ mulacc(acc, r[j], r[i-j])
+ # multiply by 2
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1])
+ emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2])
+
+ # add equal word (if any)
+ if ((i+1) % 2) != 0:
+ mulacc(acc, r[i//2], r[i//2])
+
+ # add old accumulator
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+
+ # store
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+
+regs = list(r)
+for i in xrange(init_size):
+ regs = regs[1:] + regs[:1]
+ emit("ldmia r1!, {r%s}", regs[5])
+
+ for limit in [4, 5]:
+ emit("mov r%s, #0", old_acc[1])
+ tmp = [acc[1], acc[2]]
+ acc = [acc[0], old_acc[0], old_acc[1]]
+ old_acc = tmp
+
+ # gather non-equal words
+ emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[0], regs[limit])
+ for j in xrange(1, (limit+1)//2):
+ mulacc(acc, regs[j], regs[limit-j])
+
+ emit("ldr r14, [r0]") # load stored value from initial block, and add to accumulator
+ emit("adds r%s, r%s, r14", acc[0], acc[0])
+ emit("adcs r%s, r%s, #0", acc[1], acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+
+ # multiply by 2
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1])
+ emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2])
+
+ # add equal word
+ if limit == 4:
+ mulacc(acc, regs[2], regs[2])
+
+ # add old accumulator
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+
+ # store
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+
+for i in xrange(1, s-3):
+ emit("mov r%s, #0", old_acc[1])
+ tmp = [acc[1], acc[2]]
+ acc = [acc[0], old_acc[0], old_acc[1]]
+ old_acc = tmp
+
+ # gather non-equal words
+ emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[i], regs[s - 1])
+ for j in xrange(1, (s-i)//2):
+ mulacc(acc, regs[i+j], regs[s - 1 - j])
+
+ # multiply by 2
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1])
+ emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2])
+
+ # add equal word (if any)
+ if ((s-i) % 2) != 0:
+ mulacc(acc, regs[i + (s-i)//2], regs[i + (s-i)//2])
+
+ # add old accumulator
+ emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0])
+ emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+ emit("adc r%s, r%s, #0", acc[2], acc[2])
+
+ # store
+ emit("stmia r0!, {r%s}", acc[0])
+ print ""
+
+acc = acc[1:] + acc[:1]
+emit("mov r%s, #0", acc[2])
+emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 3], regs[s - 1])
+emit("adds r1, r1, r1")
+emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1])
+emit("adc r%s, r%s, #0", acc[2], acc[2])
+emit("adds r%s, r%s, r1", acc[0], acc[0])
+emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+emit("adc r%s, r%s, #0", acc[2], acc[2])
+emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 2])
+emit("adds r%s, r%s, r1", acc[0], acc[0])
+emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+emit("adc r%s, r%s, #0", acc[2], acc[2])
+emit("stmia r0!, {r%s}", acc[0])
+print ""
+
+acc = acc[1:] + acc[:1]
+emit("mov r%s, #0", acc[2])
+emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 1])
+emit("adds r1, r1, r1")
+emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1])
+emit("adc r%s, r%s, #0", acc[2], acc[2])
+emit("adds r%s, r%s, r1", acc[0], acc[0])
+emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+emit("adc r%s, r%s, #0", acc[2], acc[2])
+emit("stmia r0!, {r%s}", acc[0])
+print ""
+
+acc = acc[1:] + acc[:1]
+emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 1], regs[s - 1])
+emit("adds r%s, r%s, r1", acc[0], acc[0])
+emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1])
+emit("stmia r0!, {r%s}", acc[0])
+emit("stmia r0!, {r%s}", acc[1])
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py
new file mode 100755
index 00000000..6571c3b3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/scripts/square_avr.py
@@ -0,0 +1,327 @@
+#!/usr/bin/env python
+
+import sys
+
+if len(sys.argv) < 2:
+ print "Provide the integer size in bytes"
+ sys.exit(1)
+
+size = int(sys.argv[1])
+
+if size > 40:
+ print "This script doesn't work with integer size %s due to laziness" % (size)
+ sys.exit(1)
+
+init_size = size - 20
+if size < 20:
+ init_size = 0
+
+def rg(i):
+ return i + 2
+
+def lo(i):
+ return i + 2
+
+def hi(i):
+ return i + 12
+
+def emit(line, *args):
+ s = '"' + line + r' \n\t"'
+ print s % args
+
+#### set up registers
+zero = "r25"
+emit("ldi %s, 0", zero) # zero register
+
+if init_size > 0:
+ emit("movw r28, r26") # y = x
+ h = (init_size + 1)//2
+
+ for i in xrange(h):
+ emit("ld r%s, x+", lo(i))
+ emit("adiw r28, %s", size - init_size) # move y to other end
+ for i in xrange(h):
+ emit("ld r%s, y+", hi(i))
+
+ emit("adiw r30, %s", size - init_size) # move z
+
+ if init_size == 1:
+ emit("mul %s, %s", lo(0), hi(0))
+ emit("st z+, r0")
+ emit("st z+, r1")
+ else:
+ #### first one
+ print ""
+ emit("ldi r23, 0")
+ emit("mul %s, %s", lo(0), hi(0))
+ emit("st z+, r0")
+ emit("mov r22, r1")
+ print ""
+
+ #### rest of initial block, with moving accumulator registers
+ acc = [22, 23, 24]
+ for r in xrange(1, h):
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, (r+2)//2):
+ emit("mul r%s, r%s", lo(i), hi(r - i))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ lo_r = range(2, 2 + h)
+ hi_r = range(12, 12 + h)
+
+ # now we need to start loading more from the high end
+ for r in xrange(h, init_size):
+ hi_r = hi_r[1:] + hi_r[:1]
+ emit("ld r%s, y+", hi_r[h-1])
+
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, (r+2)//2):
+ emit("mul r%s, r%s", lo(i), hi_r[h - 1 - i])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ # loaded all of the high end bytes; now need to start loading the rest of the low end
+ for r in xrange(1, init_size-h):
+ lo_r = lo_r[1:] + lo_r[:1]
+ emit("ld r%s, x+", lo_r[h-1])
+
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, (init_size+1 - r)//2):
+ emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+
+ lo_r = lo_r[1:] + lo_r[:1]
+ emit("ld r%s, x+", lo_r[h-1])
+
+ # now we have loaded everything, and we just need to finish the last corner
+ for r in xrange(init_size-h, init_size-1):
+ emit("ldi r%s, 0", acc[2])
+ for i in xrange(0, (init_size+1 - r)//2):
+ emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+ emit("st z+, r%s", acc[0])
+ print ""
+ acc = acc[1:] + acc[:1]
+ lo_r = lo_r[1:] + lo_r[:1] # make the indexing easy
+
+ emit("mul r%s, r%s", lo_r[0], hi_r[h - 1])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("st z+, r%s", acc[0])
+ emit("st z+, r%s", acc[1])
+ print ""
+ emit("sbiw r26, %s", init_size) # reset x
+ emit("sbiw r30, %s", size + init_size) # reset z
+
+# TODO you could do more rows of size 20 here if your integers are larger than 40 bytes
+
+s = size - init_size
+
+for i in xrange(s):
+ emit("ld r%s, x+", rg(i))
+
+#### first few columns
+# NOTE: this is only valid if size >= 3
+print ""
+emit("ldi r23, 0")
+emit("mul r%s, r%s", rg(0), rg(0))
+emit("st z+, r0")
+emit("mov r22, r1")
+print ""
+emit("ldi r24, 0")
+emit("mul r%s, r%s", rg(0), rg(1))
+emit("add r22, r0")
+emit("adc r23, r1")
+emit("adc r24, %s", zero)
+emit("add r22, r0")
+emit("adc r23, r1")
+emit("adc r24, %s", zero)
+emit("st z+, r22")
+print ""
+emit("ldi r22, 0")
+emit("mul r%s, r%s", rg(0), rg(2))
+emit("add r23, r0")
+emit("adc r24, r1")
+emit("adc r22, %s", zero)
+emit("add r23, r0")
+emit("adc r24, r1")
+emit("adc r22, %s", zero)
+emit("mul r%s, r%s", rg(1), rg(1))
+emit("add r23, r0")
+emit("adc r24, r1")
+emit("adc r22, %s", zero)
+emit("st z+, r23")
+print ""
+
+acc = [23, 24, 22]
+old_acc = [28, 29]
+for i in xrange(3, s):
+ emit("ldi r%s, 0", old_acc[1])
+ tmp = [acc[1], acc[2]]
+ acc = [acc[0], old_acc[0], old_acc[1]]
+ old_acc = tmp
+
+ # gather non-equal words
+ emit("mul r%s, r%s", rg(0), rg(i))
+ emit("mov r%s, r0", acc[0])
+ emit("mov r%s, r1", acc[1])
+ for j in xrange(1, (i+1)//2):
+ emit("mul r%s, r%s", rg(j), rg(i-j))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+ # multiply by 2
+ emit("lsl r%s", acc[0])
+ emit("rol r%s", acc[1])
+ emit("rol r%s", acc[2])
+
+ # add equal word (if any)
+ if ((i+1) % 2) != 0:
+ emit("mul r%s, r%s", rg(i//2), rg(i//2))
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ # add old accumulator
+ emit("add r%s, r%s", acc[0], old_acc[0])
+ emit("adc r%s, r%s", acc[1], old_acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ # store
+ emit("st z+, r%s", acc[0])
+ print ""
+
+regs = range(2, 22)
+for i in xrange(init_size):
+ regs = regs[1:] + regs[:1]
+ emit("ld r%s, x+", regs[19])
+
+ for limit in [18, 19]:
+ emit("ldi r%s, 0", old_acc[1])
+ tmp = [acc[1], acc[2]]
+ acc = [acc[0], old_acc[0], old_acc[1]]
+ old_acc = tmp
+
+ # gather non-equal words
+ emit("mul r%s, r%s", regs[0], regs[limit])
+ emit("mov r%s, r0", acc[0])
+ emit("mov r%s, r1", acc[1])
+ for j in xrange(1, (limit+1)//2):
+ emit("mul r%s, r%s", regs[j], regs[limit-j])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment)
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r25", acc[1])
+ emit("adc r%s, r25", acc[2])
+
+ # multiply by 2
+ emit("lsl r%s", acc[0])
+ emit("rol r%s", acc[1])
+ emit("rol r%s", acc[2])
+
+ # add equal word
+ if limit == 18:
+ emit("mul r%s, r%s", regs[9], regs[9])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ # add old accumulator
+ emit("add r%s, r%s", acc[0], old_acc[0])
+ emit("adc r%s, r%s", acc[1], old_acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ # store
+ emit("st z+, r%s", acc[0])
+ print ""
+
+for i in xrange(1, s-3):
+ emit("ldi r%s, 0", old_acc[1])
+ tmp = [acc[1], acc[2]]
+ acc = [acc[0], old_acc[0], old_acc[1]]
+ old_acc = tmp
+
+ # gather non-equal words
+ emit("mul r%s, r%s", regs[i], regs[s - 1])
+ emit("mov r%s, r0", acc[0])
+ emit("mov r%s, r1", acc[1])
+ for j in xrange(1, (s-i)//2):
+ emit("mul r%s, r%s", regs[i+j], regs[s - 1 - j])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+ # multiply by 2
+ emit("lsl r%s", acc[0])
+ emit("rol r%s", acc[1])
+ emit("rol r%s", acc[2])
+
+ # add equal word (if any)
+ if ((s-i) % 2) != 0:
+ emit("mul r%s, r%s", regs[i + (s-i)//2], regs[i + (s-i)//2])
+ emit("add r%s, r0", acc[0])
+ emit("adc r%s, r1", acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ # add old accumulator
+ emit("add r%s, r%s", acc[0], old_acc[0])
+ emit("adc r%s, r%s", acc[1], old_acc[1])
+ emit("adc r%s, %s", acc[2], zero)
+
+ # store
+ emit("st z+, r%s", acc[0])
+ print ""
+
+acc = acc[1:] + acc[:1]
+emit("ldi r%s, 0", acc[2])
+emit("mul r%s, r%s", regs[17], regs[19])
+emit("add r%s, r0", acc[0])
+emit("adc r%s, r1", acc[1])
+emit("adc r%s, %s", acc[2], zero)
+emit("add r%s, r0", acc[0])
+emit("adc r%s, r1", acc[1])
+emit("adc r%s, %s", acc[2], zero)
+emit("mul r%s, r%s", regs[18], regs[18])
+emit("add r%s, r0", acc[0])
+emit("adc r%s, r1", acc[1])
+emit("adc r%s, %s", acc[2], zero)
+emit("st z+, r%s", acc[0])
+print ""
+
+acc = acc[1:] + acc[:1]
+emit("ldi r%s, 0", acc[2])
+emit("mul r%s, r%s", regs[18], regs[19])
+emit("add r%s, r0", acc[0])
+emit("adc r%s, r1", acc[1])
+emit("adc r%s, %s", acc[2], zero)
+emit("add r%s, r0", acc[0])
+emit("adc r%s, r1", acc[1])
+emit("adc r%s, %s", acc[2], zero)
+emit("st z+, r%s", acc[0])
+print ""
+
+emit("mul r%s, r%s", regs[19], regs[19])
+emit("add r%s, r0", acc[1])
+emit("adc r%s, r1", acc[2])
+emit("st z+, r%s", acc[1])
+
+emit("st z+, r%s", acc[2])
+emit("eor r1, r1")
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino
new file mode 100644
index 00000000..c3c8900d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/ecc_test/ecc_test.ino
@@ -0,0 +1,85 @@
+#include <uECC.h>
+
+extern "C" {
+
+static int RNG(uint8_t *dest, unsigned size) {
+ // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of
+ // random noise). This can take a long time to generate random data if the result of analogRead(0)
+ // doesn't change very frequently.
+ while (size) {
+ uint8_t val = 0;
+ for (unsigned i = 0; i < 8; ++i) {
+ int init = analogRead(0);
+ int count = 0;
+ while (analogRead(0) == init) {
+ ++count;
+ }
+
+ if (count == 0) {
+ val = (val << 1) | (init & 0x01);
+ } else {
+ val = (val << 1) | (count & 0x01);
+ }
+ }
+ *dest = val;
+ ++dest;
+ --size;
+ }
+ // NOTE: it would be a good idea to hash the resulting random data using SHA-256 or similar.
+ return 1;
+}
+
+} // extern "C"
+
+void setup() {
+ Serial.begin(115200);
+ Serial.print("Testing ecc\n");
+ uECC_set_rng(&RNG);
+}
+
+void loop() {
+ const struct uECC_Curve_t * curve = uECC_secp160r1();
+ uint8_t private1[21];
+ uint8_t private2[21];
+
+ uint8_t public1[40];
+ uint8_t public2[40];
+
+ uint8_t secret1[20];
+ uint8_t secret2[20];
+
+ unsigned long a = millis();
+ uECC_make_key(public1, private1, curve);
+ unsigned long b = millis();
+
+ Serial.print("Made key 1 in "); Serial.println(b-a);
+ a = millis();
+ uECC_make_key(public2, private2, curve);
+ b = millis();
+ Serial.print("Made key 2 in "); Serial.println(b-a);
+
+ a = millis();
+ int r = uECC_shared_secret(public2, private1, secret1, curve);
+ b = millis();
+ Serial.print("Shared secret 1 in "); Serial.println(b-a);
+ if (!r) {
+ Serial.print("shared_secret() failed (1)\n");
+ return;
+ }
+
+ a = millis();
+ r = uECC_shared_secret(public1, private2, secret2, curve);
+ b = millis();
+ Serial.print("Shared secret 2 in "); Serial.println(b-a);
+ if (!r) {
+ Serial.print("shared_secret() failed (2)\n");
+ return;
+ }
+
+ if (memcmp(secret1, secret2, 20) != 0) {
+ Serial.print("Shared secrets are not identical!\n");
+ } else {
+ Serial.print("Shared secrets are identical\n");
+ }
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/emk_rules.py b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/emk_rules.py
new file mode 100644
index 00000000..956ccf5f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/emk_rules.py
@@ -0,0 +1,4 @@
+c, link = emk.module("c", "link")
+link.depdirs += [
+ "$:proj:$"
+]
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compress.c b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compress.c
new file mode 100644
index 00000000..aef374cd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compress.c
@@ -0,0 +1,79 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef uECC_TEST_NUMBER_OF_ITERATIONS
+#define uECC_TEST_NUMBER_OF_ITERATIONS 256
+#endif
+
+void vli_print(char *str, uint8_t *vli, unsigned int size) {
+ printf("%s ", str);
+ for(unsigned i=0; i<size; ++i) {
+ printf("%02X ", (unsigned)vli[i]);
+ }
+ printf("\n");
+}
+
+int main() {
+ uint8_t public[64];
+ uint8_t private[32];
+ uint8_t compressed_point[33];
+ uint8_t decompressed_point[64];
+
+ int i;
+ int c;
+
+ const struct uECC_Curve_t * curves[5];
+ int num_curves = 0;
+#if uECC_SUPPORTS_secp160r1
+ curves[num_curves++] = uECC_secp160r1();
+#endif
+#if uECC_SUPPORTS_secp192r1
+ curves[num_curves++] = uECC_secp192r1();
+#endif
+#if uECC_SUPPORTS_secp224r1
+ curves[num_curves++] = uECC_secp224r1();
+#endif
+#if uECC_SUPPORTS_secp256r1
+ curves[num_curves++] = uECC_secp256r1();
+#endif
+#if uECC_SUPPORTS_secp256k1
+ curves[num_curves++] = uECC_secp256k1();
+#endif
+
+ printf("Testing compression and decompression of %d random EC points\n",
+ uECC_TEST_NUMBER_OF_ITERATIONS);
+
+ for (c = 0; c < num_curves; ++c) {
+ for (i = 0; i < uECC_TEST_NUMBER_OF_ITERATIONS; ++i) {
+ printf(".");
+ fflush(stdout);
+
+ memset(public, 0, sizeof(public));
+ memset(decompressed_point, 0, sizeof(decompressed_point));
+
+ /* Generate arbitrary EC point (public) on Curve */
+ if (!uECC_make_key(public, private, curves[c])) {
+ printf("uECC_make_key() failed\n");
+ continue;
+ }
+
+ /* compress and decompress point */
+ uECC_compress(public, compressed_point, curves[c]);
+ uECC_decompress(compressed_point, decompressed_point, curves[c]);
+
+ if (memcmp(public, decompressed_point, sizeof(public)) != 0) {
+ printf("Original and decompressed points are not identical!\n");
+ vli_print("Original point = ", public, sizeof(public));
+ vli_print("Compressed point = ", compressed_point, sizeof(compressed_point));
+ vli_print("Decompressed point = ", decompressed_point, sizeof(decompressed_point));
+ }
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compute.c b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compute.c
new file mode 100644
index 00000000..7b936d82
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_compute.c
@@ -0,0 +1,81 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <string.h>
+
+void vli_print(char *str, uint8_t *vli, unsigned int size) {
+ printf("%s ", str);
+ for(unsigned i=0; i<size; ++i) {
+ printf("%02X ", (unsigned)vli[i]);
+ }
+ printf("\n");
+}
+
+int main() {
+ int i;
+ int success;
+ uint8_t private[32];
+ uint8_t public[64];
+ uint8_t public_computed[64];
+
+ int c;
+
+ const struct uECC_Curve_t * curves[5];
+ int num_curves = 0;
+#if uECC_SUPPORTS_secp160r1
+ curves[num_curves++] = uECC_secp160r1();
+#endif
+#if uECC_SUPPORTS_secp192r1
+ curves[num_curves++] = uECC_secp192r1();
+#endif
+#if uECC_SUPPORTS_secp224r1
+ curves[num_curves++] = uECC_secp224r1();
+#endif
+#if uECC_SUPPORTS_secp256r1
+ curves[num_curves++] = uECC_secp256r1();
+#endif
+#if uECC_SUPPORTS_secp256k1
+ curves[num_curves++] = uECC_secp256k1();
+#endif
+
+ printf("Testing 256 random private key pairs\n");
+ for (c = 0; c < num_curves; ++c) {
+ for (i = 0; i < 256; ++i) {
+ printf(".");
+ fflush(stdout);
+
+ memset(public, 0, sizeof(public));
+ memset(public_computed, 0, sizeof(public_computed));
+
+ if (!uECC_make_key(public, private, curves[c])) {
+ printf("uECC_make_key() failed\n");
+ continue;
+ }
+
+ if (!uECC_compute_public_key(private, public_computed, curves[c])) {
+ printf("uECC_compute_public_key() failed\n");
+ }
+
+ if (memcmp(public, public_computed, sizeof(public)) != 0) {
+ printf("Computed and provided public keys are not identical!\n");
+ vli_print("Computed public key = ", public_computed, sizeof(public_computed));
+ vli_print("Provided public key = ", public, sizeof(public));
+ vli_print("Private key = ", private, sizeof(private));
+ }
+ }
+
+ printf("\n");
+ printf("Testing private key = 0\n");
+
+ memset(private, 0, sizeof(private));
+ success = uECC_compute_public_key(private, public_computed, curves[c]);
+ if (success) {
+ printf("uECC_compute_public_key() should have failed\n");
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c
new file mode 100644
index 00000000..7315b754
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdh.c
@@ -0,0 +1,90 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <string.h>
+
+void vli_print(uint8_t *vli, unsigned int size) {
+ for(unsigned i=0; i<size; ++i) {
+ printf("%02X ", (unsigned)vli[i]);
+ }
+}
+
+int main() {
+ int i, c;
+ uint8_t private1[32] = {0};
+ uint8_t private2[32] = {0};
+ uint8_t public1[64] = {0};
+ uint8_t public2[64] = {0};
+ uint8_t secret1[32] = {0};
+ uint8_t secret2[32] = {0};
+
+ const struct uECC_Curve_t * curves[5];
+ int num_curves = 0;
+#if uECC_SUPPORTS_secp160r1
+ curves[num_curves++] = uECC_secp160r1();
+#endif
+#if uECC_SUPPORTS_secp192r1
+ curves[num_curves++] = uECC_secp192r1();
+#endif
+#if uECC_SUPPORTS_secp224r1
+ curves[num_curves++] = uECC_secp224r1();
+#endif
+#if uECC_SUPPORTS_secp256r1
+ curves[num_curves++] = uECC_secp256r1();
+#endif
+#if uECC_SUPPORTS_secp256k1
+ curves[num_curves++] = uECC_secp256k1();
+#endif
+
+ printf("Testing 256 random private key pairs\n");
+
+ for (c = 0; c < num_curves; ++c) {
+ for (i = 0; i < 256; ++i) {
+ printf(".");
+ fflush(stdout);
+
+ if (!uECC_make_key(public1, private1, curves[c]) ||
+ !uECC_make_key(public2, private2, curves[c])) {
+ printf("uECC_make_key() failed\n");
+ return 1;
+ }
+
+ if (!uECC_shared_secret(public2, private1, secret1, curves[c])) {
+ printf("shared_secret() failed (1)\n");
+ return 1;
+ }
+
+ if (!uECC_shared_secret(public1, private2, secret2, curves[c])) {
+ printf("shared_secret() failed (2)\n");
+ return 1;
+ }
+
+ if (memcmp(secret1, secret2, sizeof(secret1)) != 0) {
+ printf("Shared secrets are not identical!\n");
+ printf("Private key 1 = ");
+ vli_print(private1, 32);
+ printf("\n");
+ printf("Private key 2 = ");
+ vli_print(private2, 32);
+ printf("\n");
+ printf("Public key 1 = ");
+ vli_print(public1, 64);
+ printf("\n");
+ printf("Public key 2 = ");
+ vli_print(public2, 64);
+ printf("\n");
+ printf("Shared secret 1 = ");
+ vli_print(secret1, 32);
+ printf("\n");
+ printf("Shared secret 2 = ");
+ vli_print(secret2, 32);
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c
new file mode 100644
index 00000000..86997949
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa.c
@@ -0,0 +1,59 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int main() {
+ int i, c;
+ uint8_t private[32] = {0};
+ uint8_t public[64] = {0};
+ uint8_t hash[32] = {0};
+ uint8_t sig[64] = {0};
+
+ const struct uECC_Curve_t * curves[5];
+ int num_curves = 0;
+#if uECC_SUPPORTS_secp160r1
+ curves[num_curves++] = uECC_secp160r1();
+#endif
+#if uECC_SUPPORTS_secp192r1
+ curves[num_curves++] = uECC_secp192r1();
+#endif
+#if uECC_SUPPORTS_secp224r1
+ curves[num_curves++] = uECC_secp224r1();
+#endif
+#if uECC_SUPPORTS_secp256r1
+ curves[num_curves++] = uECC_secp256r1();
+#endif
+#if uECC_SUPPORTS_secp256k1
+ curves[num_curves++] = uECC_secp256k1();
+#endif
+
+ printf("Testing 256 signatures\n");
+ for (c = 0; c < num_curves; ++c) {
+ for (i = 0; i < 256; ++i) {
+ printf(".");
+ fflush(stdout);
+
+ if (!uECC_make_key(public, private, curves[c])) {
+ printf("uECC_make_key() failed\n");
+ return 1;
+ }
+ memcpy(hash, public, sizeof(hash));
+
+ if (!uECC_sign(private, hash, sizeof(hash), sig, curves[c])) {
+ printf("uECC_sign() failed\n");
+ return 1;
+ }
+
+ if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) {
+ printf("uECC_verify() failed\n");
+ return 1;
+ }
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example
new file mode 100644
index 00000000..df9aa101
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/test/test_ecdsa_deterministic.c.example
@@ -0,0 +1,93 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define SHA256_BLOCK_LENGTH 64
+#define SHA256_DIGEST_LENGTH 32
+
+typedef struct SHA256_CTX {
+ uint32_t state[8];
+ uint64_t bitcount;
+ uint8_t buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+
+extern void SHA256_Init(SHA256_CTX *ctx);
+extern void SHA256_Update(SHA256_CTX *ctx, const uint8_t *message, size_t message_size);
+extern void SHA256_Final(uint8_t digest[SHA256_DIGEST_LENGTH], SHA256_CTX *ctx);
+
+typedef struct SHA256_HashContext {
+ uECC_HashContext uECC;
+ SHA256_CTX ctx;
+} SHA256_HashContext;
+
+static void init_SHA256(const uECC_HashContext *base) {
+ SHA256_HashContext *context = (SHA256_HashContext *)base;
+ SHA256_Init(&context->ctx);
+}
+
+static void update_SHA256(const uECC_HashContext *base,
+ const uint8_t *message,
+ unsigned message_size) {
+ SHA256_HashContext *context = (SHA256_HashContext *)base;
+ SHA256_Update(&context->ctx, message, message_size);
+}
+
+static void finish_SHA256(const uECC_HashContext *base, uint8_t *hash_result) {
+ SHA256_HashContext *context = (SHA256_HashContext *)base;
+ SHA256_Final(hash_result, &context->ctx);
+}
+
+int main() {
+ int i, c;
+ uint8_t private[32] = {0};
+ uint8_t public[64] = {0};
+ uint8_t hash[32] = {0};
+ uint8_t sig[64] = {0};
+
+ uint8_t tmp[2 * SHA256_DIGEST_LENGTH + SHA256_BLOCK_LENGTH];
+ SHA256_HashContext ctx = {{
+ &init_SHA256,
+ &update_SHA256,
+ &finish_SHA256,
+ SHA256_BLOCK_LENGTH,
+ SHA256_DIGEST_LENGTH,
+ tmp
+ }};
+
+ const struct uECC_Curve_t * curves[5];
+ curves[0] = uECC_secp160r1();
+ curves[1] = uECC_secp192r1();
+ curves[2] = uECC_secp224r1();
+ curves[3] = uECC_secp256r1();
+ curves[4] = uECC_secp256k1();
+
+ printf("Testing 256 signatures\n");
+ for (c = 0; c < 5; ++c) {
+ for (i = 0; i < 256; ++i) {
+ printf(".");
+ fflush(stdout);
+
+ if (!uECC_make_key(public, private, curves[c])) {
+ printf("uECC_make_key() failed\n");
+ return 1;
+ }
+ memcpy(hash, public, sizeof(hash));
+
+ if (!uECC_sign_deterministic(private, hash, sizeof(hash), &ctx.uECC, sig, curves[c])) {
+ printf("uECC_sign() failed\n");
+ return 1;
+ }
+
+ if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) {
+ printf("uECC_verify() failed\n");
+ return 1;
+ }
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/types.h b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/types.h
new file mode 100644
index 00000000..9ee81438
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/types.h
@@ -0,0 +1,108 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_TYPES_H_
+#define _UECC_TYPES_H_
+
+#ifndef uECC_PLATFORM
+ #if __AVR__
+ #define uECC_PLATFORM uECC_avr
+ #elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */
+ #define uECC_PLATFORM uECC_arm_thumb2
+ #elif defined(__thumb__)
+ #define uECC_PLATFORM uECC_arm_thumb
+ #elif defined(__arm__) || defined(_M_ARM)
+ #define uECC_PLATFORM uECC_arm
+ #elif defined(__aarch64__)
+ #define uECC_PLATFORM uECC_arm64
+ #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__)
+ #define uECC_PLATFORM uECC_x86
+ #elif defined(__amd64__) || defined(_M_X64)
+ #define uECC_PLATFORM uECC_x86_64
+ #else
+ #define uECC_PLATFORM uECC_arch_other
+ #endif
+#endif
+
+#ifndef uECC_ARM_USE_UMAAL
+ #if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6)
+ #define uECC_ARM_USE_UMAAL 1
+ #elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && !__ARM_ARCH_7M__
+ #define uECC_ARM_USE_UMAAL 1
+ #else
+ #define uECC_ARM_USE_UMAAL 0
+ #endif
+#endif
+
+#ifndef uECC_WORD_SIZE
+ #if uECC_PLATFORM == uECC_avr
+ #define uECC_WORD_SIZE 1
+ #elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64)
+ #define uECC_WORD_SIZE 8
+ #else
+ #define uECC_WORD_SIZE 4
+ #endif
+#endif
+
+#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8)
+ #error "Unsupported value for uECC_WORD_SIZE"
+#endif
+
+#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
+ #pragma message ("uECC_WORD_SIZE must be 1 for AVR")
+ #undef uECC_WORD_SIZE
+ #define uECC_WORD_SIZE 1
+#endif
+
+#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
+ uECC_PLATFORM == uECC_arm_thumb2) && \
+ (uECC_WORD_SIZE != 4))
+ #pragma message ("uECC_WORD_SIZE must be 4 for ARM")
+ #undef uECC_WORD_SIZE
+ #define uECC_WORD_SIZE 4
+#endif
+
+#if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302)
+ #define SUPPORTS_INT128 1
+#else
+ #define SUPPORTS_INT128 0
+#endif
+
+typedef int8_t wordcount_t;
+typedef int16_t bitcount_t;
+typedef int8_t cmpresult_t;
+
+#if (uECC_WORD_SIZE == 1)
+
+typedef uint8_t uECC_word_t;
+typedef uint16_t uECC_dword_t;
+
+#define HIGH_BIT_SET 0x80
+#define uECC_WORD_BITS 8
+#define uECC_WORD_BITS_SHIFT 3
+#define uECC_WORD_BITS_MASK 0x07
+
+#elif (uECC_WORD_SIZE == 4)
+
+typedef uint32_t uECC_word_t;
+typedef uint64_t uECC_dword_t;
+
+#define HIGH_BIT_SET 0x80000000
+#define uECC_WORD_BITS 32
+#define uECC_WORD_BITS_SHIFT 5
+#define uECC_WORD_BITS_MASK 0x01F
+
+#elif (uECC_WORD_SIZE == 8)
+
+typedef uint64_t uECC_word_t;
+#if SUPPORTS_INT128
+typedef unsigned __int128 uECC_dword_t;
+#endif
+
+#define HIGH_BIT_SET 0x8000000000000000ull
+#define uECC_WORD_BITS 64
+#define uECC_WORD_BITS_SHIFT 6
+#define uECC_WORD_BITS_MASK 0x03F
+
+#endif /* uECC_WORD_SIZE */
+
+#endif /* _UECC_TYPES_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.c b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.c
new file mode 100644
index 00000000..daa144a5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.c
@@ -0,0 +1,1634 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#include "uECC.h"
+#include "uECC_vli.h"
+
+#ifndef uECC_RNG_MAX_TRIES
+ #define uECC_RNG_MAX_TRIES 64
+#endif
+
+#if uECC_ENABLE_VLI_API
+ #define uECC_VLI_API
+#else
+ #define uECC_VLI_API static
+#endif
+
+#define CONCATX(a, ...) a ## __VA_ARGS__
+#define CONCAT(a, ...) CONCATX(a, __VA_ARGS__)
+
+#define STRX(a) #a
+#define STR(a) STRX(a)
+
+#define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
+#define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
+#define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
+#define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
+#define EVAL4(...) __VA_ARGS__
+
+#define DEC_1 0
+#define DEC_2 1
+#define DEC_3 2
+#define DEC_4 3
+#define DEC_5 4
+#define DEC_6 5
+#define DEC_7 6
+#define DEC_8 7
+#define DEC_9 8
+#define DEC_10 9
+#define DEC_11 10
+#define DEC_12 11
+#define DEC_13 12
+#define DEC_14 13
+#define DEC_15 14
+#define DEC_16 15
+#define DEC_17 16
+#define DEC_18 17
+#define DEC_19 18
+#define DEC_20 19
+#define DEC_21 20
+#define DEC_22 21
+#define DEC_23 22
+#define DEC_24 23
+#define DEC_25 24
+#define DEC_26 25
+#define DEC_27 26
+#define DEC_28 27
+#define DEC_29 28
+#define DEC_30 29
+#define DEC_31 30
+#define DEC_32 31
+
+#define DEC(N) CONCAT(DEC_, N)
+
+#define SECOND_ARG(_, val, ...) val
+#define SOME_CHECK_0 ~, 0
+#define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME,)
+#define SOME_OR_0(N) GET_SECOND_ARG(CONCAT(SOME_CHECK_, N))
+
+#define EMPTY(...)
+#define DEFER(...) __VA_ARGS__ EMPTY()
+
+#define REPEAT_NAME_0() REPEAT_0
+#define REPEAT_NAME_SOME() REPEAT_SOME
+#define REPEAT_0(...)
+#define REPEAT_SOME(N, stuff) DEFER(CONCAT(REPEAT_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), stuff) stuff
+#define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff))
+
+#define REPEATM_NAME_0() REPEATM_0
+#define REPEATM_NAME_SOME() REPEATM_SOME
+#define REPEATM_0(...)
+#define REPEATM_SOME(N, macro) macro(N) \
+ DEFER(CONCAT(REPEATM_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), macro)
+#define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro))
+
+#include "platform-specific.inc"
+
+#if (uECC_WORD_SIZE == 1)
+ #if uECC_SUPPORTS_secp160r1
+ #define uECC_MAX_WORDS 21 /* Due to the size of curve_n. */
+ #endif
+ #if uECC_SUPPORTS_secp192r1
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 24
+ #endif
+ #if uECC_SUPPORTS_secp224r1
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 28
+ #endif
+ #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 32
+ #endif
+#elif (uECC_WORD_SIZE == 4)
+ #if uECC_SUPPORTS_secp160r1
+ #define uECC_MAX_WORDS 6 /* Due to the size of curve_n. */
+ #endif
+ #if uECC_SUPPORTS_secp192r1
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 6
+ #endif
+ #if uECC_SUPPORTS_secp224r1
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 7
+ #endif
+ #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 8
+ #endif
+#elif (uECC_WORD_SIZE == 8)
+ #if uECC_SUPPORTS_secp160r1
+ #define uECC_MAX_WORDS 3
+ #endif
+ #if uECC_SUPPORTS_secp192r1
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 3
+ #endif
+ #if uECC_SUPPORTS_secp224r1
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 4
+ #endif
+ #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1)
+ #undef uECC_MAX_WORDS
+ #define uECC_MAX_WORDS 4
+ #endif
+#endif /* uECC_WORD_SIZE */
+
+#define BITS_TO_WORDS(num_bits) ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
+#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
+
+struct uECC_Curve_t {
+ wordcount_t num_words;
+ wordcount_t num_bytes;
+ bitcount_t num_n_bits;
+ uECC_word_t p[uECC_MAX_WORDS];
+ uECC_word_t n[uECC_MAX_WORDS];
+ uECC_word_t G[uECC_MAX_WORDS * 2];
+ uECC_word_t b[uECC_MAX_WORDS];
+ void (*double_jacobian)(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * Z1,
+ uECC_Curve curve);
+#if uECC_SUPPORT_COMPRESSED_POINT
+ void (*mod_sqrt)(uECC_word_t *a, uECC_Curve curve);
+#endif
+ void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
+#endif
+};
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+static void bcopy(uint8_t *dst,
+ const uint8_t *src,
+ unsigned num_bytes) {
+ while (0 != num_bytes) {
+ num_bytes--;
+ dst[num_bytes] = src[num_bytes];
+ }
+}
+#endif
+
+static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words);
+
+#if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
+ uECC_PLATFORM == uECC_arm_thumb2)
+ #include "asm_arm.inc"
+#endif
+
+#if (uECC_PLATFORM == uECC_avr)
+ #include "asm_avr.inc"
+#endif
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_RNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+void uECC_set_rng(uECC_RNG_Function rng_function) {
+ g_rng_function = rng_function;
+}
+
+uECC_RNG_Function uECC_get_rng(void) {
+ return g_rng_function;
+}
+
+int uECC_curve_private_key_size(uECC_Curve curve) {
+ return BITS_TO_BYTES(curve->num_n_bits);
+}
+
+int uECC_curve_public_key_size(uECC_Curve curve) {
+ return 2 * curve->num_bytes;
+}
+
+#if !asm_clear
+uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ vli[i] = 0;
+ }
+}
+#endif /* !asm_clear */
+
+/* Constant-time comparison to zero - secure way to compare long integers */
+/* Returns 1 if vli == 0, 0 otherwise. */
+uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) {
+ uECC_word_t bits = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ bits |= vli[i];
+ }
+ return (bits == 0);
+}
+
+/* Returns nonzero if bit 'bit' of vli is set. */
+uECC_VLI_API uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) {
+ return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
+}
+
+/* Counts the number of words in vli. */
+static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) {
+ wordcount_t i;
+ /* Search from the end until we find a non-zero digit.
+ We do it in reverse because we expect that most digits will be nonzero. */
+ for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
+ }
+
+ return (i + 1);
+}
+
+/* Counts the number of bits required to represent vli. */
+uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) {
+ uECC_word_t i;
+ uECC_word_t digit;
+
+ wordcount_t num_digits = vli_numDigits(vli, max_words);
+ if (num_digits == 0) {
+ return 0;
+ }
+
+ digit = vli[num_digits - 1];
+ for (i = 0; digit; ++i) {
+ digit >>= 1;
+ }
+
+ return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
+}
+
+/* Sets dest = src. */
+#if !asm_set
+uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) {
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ dest[i] = src[i];
+ }
+}
+#endif /* !asm_set */
+
+/* Returns sign of left - right. */
+static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ wordcount_t i;
+ for (i = num_words - 1; i >= 0; --i) {
+ if (left[i] > right[i]) {
+ return 1;
+ } else if (left[i] < right[i]) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Constant-time comparison function - secure way to compare long integers */
+/* Returns one if left == right, zero otherwise. */
+uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uECC_word_t diff = 0;
+ wordcount_t i;
+ for (i = num_words - 1; i >= 0; --i) {
+ diff |= (left[i] ^ right[i]);
+ }
+ return (diff == 0);
+}
+
+uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words);
+
+/* Returns sign of left - right, in constant time. */
+uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uECC_word_t tmp[uECC_MAX_WORDS];
+ uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
+ uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
+ return (!equal - 2 * neg);
+}
+
+/* Computes vli = vli >> 1. */
+#if !asm_rshift1
+uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) {
+ uECC_word_t *end = vli;
+ uECC_word_t carry = 0;
+
+ vli += num_words;
+ while (vli-- > end) {
+ uECC_word_t temp = *vli;
+ *vli = (temp >> 1) | carry;
+ carry = temp << (uECC_WORD_BITS - 1);
+ }
+}
+#endif /* !asm_rshift1 */
+
+/* Computes result = left + right, returning carry. Can modify in place. */
+#if !asm_add
+uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uECC_word_t carry = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ uECC_word_t sum = left[i] + right[i] + carry;
+ if (sum != left[i]) {
+ carry = (sum < left[i]);
+ }
+ result[i] = sum;
+ }
+ return carry;
+}
+#endif /* !asm_add */
+
+/* Computes result = left - right, returning borrow. Can modify in place. */
+#if !asm_sub
+uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uECC_word_t borrow = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ uECC_word_t diff = left[i] - right[i] - borrow;
+ if (diff != left[i]) {
+ borrow = (diff > left[i]);
+ }
+ result[i] = diff;
+ }
+ return borrow;
+}
+#endif /* !asm_sub */
+
+#if !asm_mult || (uECC_SQUARE_FUNC && !asm_square) || \
+ (uECC_SUPPORTS_secp256k1 && (uECC_OPTIMIZATION_LEVEL > 0) && \
+ ((uECC_WORD_SIZE == 1) || (uECC_WORD_SIZE == 8)))
+static void muladd(uECC_word_t a,
+ uECC_word_t b,
+ uECC_word_t *r0,
+ uECC_word_t *r1,
+ uECC_word_t *r2) {
+#if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128
+ uint64_t a0 = a & 0xffffffffull;
+ uint64_t a1 = a >> 32;
+ uint64_t b0 = b & 0xffffffffull;
+ uint64_t b1 = b >> 32;
+
+ uint64_t i0 = a0 * b0;
+ uint64_t i1 = a0 * b1;
+ uint64_t i2 = a1 * b0;
+ uint64_t i3 = a1 * b1;
+
+ uint64_t p0, p1;
+
+ i2 += (i0 >> 32);
+ i2 += i1;
+ if (i2 < i1) { /* overflow */
+ i3 += 0x100000000ull;
+ }
+
+ p0 = (i0 & 0xffffffffull) | (i2 << 32);
+ p1 = i3 + (i2 >> 32);
+
+ *r0 += p0;
+ *r1 += (p1 + (*r0 < p0));
+ *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0));
+#else
+ uECC_dword_t p = (uECC_dword_t)a * b;
+ uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
+ r01 += p;
+ *r2 += (r01 < p);
+ *r1 = r01 >> uECC_WORD_BITS;
+ *r0 = (uECC_word_t)r01;
+#endif
+}
+#endif /* muladd needed */
+
+#if !asm_mult
+uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words) {
+ uECC_word_t r0 = 0;
+ uECC_word_t r1 = 0;
+ uECC_word_t r2 = 0;
+ wordcount_t i, k;
+
+ /* Compute each digit of result in sequence, maintaining the carries. */
+ for (k = 0; k < num_words; ++k) {
+ for (i = 0; i <= k; ++i) {
+ muladd(left[i], right[k - i], &r0, &r1, &r2);
+ }
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+ for (k = num_words; k < num_words * 2 - 1; ++k) {
+ for (i = (k + 1) - num_words; i < num_words; ++i) {
+ muladd(left[i], right[k - i], &r0, &r1, &r2);
+ }
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+ result[num_words * 2 - 1] = r0;
+}
+#endif /* !asm_mult */
+
+#if uECC_SQUARE_FUNC
+
+#if !asm_square
+static void mul2add(uECC_word_t a,
+ uECC_word_t b,
+ uECC_word_t *r0,
+ uECC_word_t *r1,
+ uECC_word_t *r2) {
+#if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128
+ uint64_t a0 = a & 0xffffffffull;
+ uint64_t a1 = a >> 32;
+ uint64_t b0 = b & 0xffffffffull;
+ uint64_t b1 = b >> 32;
+
+ uint64_t i0 = a0 * b0;
+ uint64_t i1 = a0 * b1;
+ uint64_t i2 = a1 * b0;
+ uint64_t i3 = a1 * b1;
+
+ uint64_t p0, p1;
+
+ i2 += (i0 >> 32);
+ i2 += i1;
+ if (i2 < i1)
+ { /* overflow */
+ i3 += 0x100000000ull;
+ }
+
+ p0 = (i0 & 0xffffffffull) | (i2 << 32);
+ p1 = i3 + (i2 >> 32);
+
+ *r2 += (p1 >> 63);
+ p1 = (p1 << 1) | (p0 >> 63);
+ p0 <<= 1;
+
+ *r0 += p0;
+ *r1 += (p1 + (*r0 < p0));
+ *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0));
+#else
+ uECC_dword_t p = (uECC_dword_t)a * b;
+ uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
+ *r2 += (p >> (uECC_WORD_BITS * 2 - 1));
+ p *= 2;
+ r01 += p;
+ *r2 += (r01 < p);
+ *r1 = r01 >> uECC_WORD_BITS;
+ *r0 = (uECC_word_t)r01;
+#endif
+}
+
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+ uECC_word_t r0 = 0;
+ uECC_word_t r1 = 0;
+ uECC_word_t r2 = 0;
+
+ wordcount_t i, k;
+
+ for (k = 0; k < num_words * 2 - 1; ++k) {
+ uECC_word_t min = (k < num_words ? 0 : (k + 1) - num_words);
+ for (i = min; i <= k && i <= k - i; ++i) {
+ if (i < k-i) {
+ mul2add(left[i], left[k - i], &r0, &r1, &r2);
+ } else {
+ muladd(left[i], left[k - i], &r0, &r1, &r2);
+ }
+ }
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+
+ result[num_words * 2 - 1] = r0;
+}
+#endif /* !asm_square */
+
+#else /* uECC_SQUARE_FUNC */
+
+#if uECC_ENABLE_VLI_API
+uECC_VLI_API void uECC_vli_square(uECC_word_t *result,
+ const uECC_word_t *left,
+ wordcount_t num_words) {
+ uECC_vli_mult(result, left, left, num_words);
+}
+#endif /* uECC_ENABLE_VLI_API */
+
+#endif /* uECC_SQUARE_FUNC */
+
+/* Computes result = (left + right) % mod.
+ Assumes that left < mod and right < mod, and that result does not overlap mod. */
+uECC_VLI_API void uECC_vli_modAdd(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
+ if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
+ /* result > mod (result = mod + remainder), so subtract mod to get remainder. */
+ uECC_vli_sub(result, result, mod, num_words);
+ }
+}
+
+/* Computes result = (left - right) % mod.
+ Assumes that left < mod and right < mod, and that result does not overlap mod. */
+uECC_VLI_API void uECC_vli_modSub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
+ if (l_borrow) {
+ /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
+ we can get the correct result from result + mod (with overflow). */
+ uECC_vli_add(result, result, mod, num_words);
+ }
+}
+
+/* Computes result = product % mod, where product is 2N words long. */
+/* Currently only designed to work for curve_p or curve_n. */
+uECC_VLI_API void uECC_vli_mmod(uECC_word_t *result,
+ uECC_word_t *product,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t mod_multiple[2 * uECC_MAX_WORDS];
+ uECC_word_t tmp[2 * uECC_MAX_WORDS];
+ uECC_word_t *v[2] = {tmp, product};
+ uECC_word_t index;
+
+ /* Shift mod so its highest set bit is at the maximum position. */
+ bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
+ wordcount_t word_shift = shift / uECC_WORD_BITS;
+ wordcount_t bit_shift = shift % uECC_WORD_BITS;
+ uECC_word_t carry = 0;
+ uECC_vli_clear(mod_multiple, word_shift);
+ if (bit_shift > 0) {
+ for(index = 0; index < (uECC_word_t)num_words; ++index) {
+ mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
+ carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
+ }
+ } else {
+ uECC_vli_set(mod_multiple + word_shift, mod, num_words);
+ }
+
+ for (index = 1; shift >= 0; --shift) {
+ uECC_word_t borrow = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words * 2; ++i) {
+ uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
+ if (diff != v[index][i]) {
+ borrow = (diff > v[index][i]);
+ }
+ v[1 - index][i] = diff;
+ }
+ index = !(index ^ borrow); /* Swap the index if there was no borrow */
+ uECC_vli_rshift1(mod_multiple, num_words);
+ mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
+ uECC_vli_rshift1(mod_multiple + num_words, num_words);
+ }
+ uECC_vli_set(result, v[index], num_words);
+}
+
+/* Computes result = (left * right) % mod. */
+uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t product[2 * uECC_MAX_WORDS];
+ uECC_vli_mult(product, left, right, num_words);
+ uECC_vli_mmod(result, product, mod, num_words);
+}
+
+uECC_VLI_API void uECC_vli_modMult_fast(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ uECC_Curve curve) {
+ uECC_word_t product[2 * uECC_MAX_WORDS];
+ uECC_vli_mult(product, left, right, curve->num_words);
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ curve->mmod_fast(result, product);
+#else
+ uECC_vli_mmod(result, product, curve->p, curve->num_words);
+#endif
+}
+
+#if uECC_SQUARE_FUNC
+
+#if uECC_ENABLE_VLI_API
+/* Computes result = left^2 % mod. */
+uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t product[2 * uECC_MAX_WORDS];
+ uECC_vli_square(product, left, num_words);
+ uECC_vli_mmod(result, product, mod, num_words);
+}
+#endif /* uECC_ENABLE_VLI_API */
+
+uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result,
+ const uECC_word_t *left,
+ uECC_Curve curve) {
+ uECC_word_t product[2 * uECC_MAX_WORDS];
+ uECC_vli_square(product, left, curve->num_words);
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ curve->mmod_fast(result, product);
+#else
+ uECC_vli_mmod(result, product, curve->p, curve->num_words);
+#endif
+}
+
+#else /* uECC_SQUARE_FUNC */
+
+#if uECC_ENABLE_VLI_API
+uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_vli_modMult(result, left, left, mod, num_words);
+}
+#endif /* uECC_ENABLE_VLI_API */
+
+uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result,
+ const uECC_word_t *left,
+ uECC_Curve curve) {
+ uECC_vli_modMult_fast(result, left, left, curve);
+}
+
+#endif /* uECC_SQUARE_FUNC */
+
+#define EVEN(vli) (!(vli[0] & 1))
+static void vli_modInv_update(uECC_word_t *uv,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t carry = 0;
+ if (!EVEN(uv)) {
+ carry = uECC_vli_add(uv, uv, mod, num_words);
+ }
+ uECC_vli_rshift1(uv, num_words);
+ if (carry) {
+ uv[num_words - 1] |= HIGH_BIT_SET;
+ }
+}
+
+/* Computes result = (1 / input) % mod. All VLIs are the same size.
+ See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */
+uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result,
+ const uECC_word_t *input,
+ const uECC_word_t *mod,
+ wordcount_t num_words) {
+ uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS];
+ cmpresult_t cmpResult;
+
+ if (uECC_vli_isZero(input, num_words)) {
+ uECC_vli_clear(result, num_words);
+ return;
+ }
+
+ uECC_vli_set(a, input, num_words);
+ uECC_vli_set(b, mod, num_words);
+ uECC_vli_clear(u, num_words);
+ u[0] = 1;
+ uECC_vli_clear(v, num_words);
+ while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
+ if (EVEN(a)) {
+ uECC_vli_rshift1(a, num_words);
+ vli_modInv_update(u, mod, num_words);
+ } else if (EVEN(b)) {
+ uECC_vli_rshift1(b, num_words);
+ vli_modInv_update(v, mod, num_words);
+ } else if (cmpResult > 0) {
+ uECC_vli_sub(a, a, b, num_words);
+ uECC_vli_rshift1(a, num_words);
+ if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
+ uECC_vli_add(u, u, mod, num_words);
+ }
+ uECC_vli_sub(u, u, v, num_words);
+ vli_modInv_update(u, mod, num_words);
+ } else {
+ uECC_vli_sub(b, b, a, num_words);
+ uECC_vli_rshift1(b, num_words);
+ if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
+ uECC_vli_add(v, v, mod, num_words);
+ }
+ uECC_vli_sub(v, v, u, num_words);
+ vli_modInv_update(v, mod, num_words);
+ }
+ }
+ uECC_vli_set(result, u, num_words);
+}
+
+/* ------ Point operations ------ */
+
+#include "curve-specific.inc"
+
+/* Returns 1 if 'point' is the point at infinity, 0 otherwise. */
+#define EccPoint_isZero(point, curve) uECC_vli_isZero((point), (curve)->num_words * 2)
+
+/* Point multiplication algorithm using Montgomery's ladder with co-Z coordinates.
+From http://eprint.iacr.org/2011/338.pdf
+*/
+
+/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
+static void apply_z(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ const uECC_word_t * const Z,
+ uECC_Curve curve) {
+ uECC_word_t t1[uECC_MAX_WORDS];
+
+ uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
+ uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
+ uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
+ uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
+}
+
+/* P = (x1, y1) => 2P, (x2, y2) => P' */
+static void XYcZ_initial_double(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * X2,
+ uECC_word_t * Y2,
+ const uECC_word_t * const initial_Z,
+ uECC_Curve curve) {
+ uECC_word_t z[uECC_MAX_WORDS];
+ wordcount_t num_words = curve->num_words;
+ if (initial_Z) {
+ uECC_vli_set(z, initial_Z, num_words);
+ } else {
+ uECC_vli_clear(z, num_words);
+ z[0] = 1;
+ }
+
+ uECC_vli_set(X2, X1, num_words);
+ uECC_vli_set(Y2, Y1, num_words);
+
+ apply_z(X1, Y1, z, curve);
+ curve->double_jacobian(X1, Y1, z, curve);
+ apply_z(X2, Y2, z, curve);
+}
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
+ or P => P', Q => P + Q
+*/
+static void XYcZ_add(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * X2,
+ uECC_word_t * Y2,
+ uECC_Curve curve) {
+ /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+ uECC_word_t t5[uECC_MAX_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+ uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+ uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+ uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+ uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
+
+ uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
+ uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
+ uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
+ uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
+ uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
+ uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
+
+ uECC_vli_set(X2, t5, num_words);
+}
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
+ or P => P - Q, Q => P + Q
+*/
+static void XYcZ_addC(uECC_word_t * X1,
+ uECC_word_t * Y1,
+ uECC_word_t * X2,
+ uECC_word_t * Y2,
+ uECC_Curve curve) {
+ /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+ uECC_word_t t5[uECC_MAX_WORDS];
+ uECC_word_t t6[uECC_MAX_WORDS];
+ uECC_word_t t7[uECC_MAX_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+ uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+ uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+ uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+ uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+
+ uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
+ uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
+ uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
+ uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
+ uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
+
+ uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
+ uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */
+
+ uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
+ uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
+ uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
+ uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
+ uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */
+
+ uECC_vli_set(X1, t7, num_words);
+}
+
+/* result may overlap point. */
+static void EccPoint_mult(uECC_word_t * result,
+ const uECC_word_t * point,
+ const uECC_word_t * scalar,
+ const uECC_word_t * initial_Z,
+ bitcount_t num_bits,
+ uECC_Curve curve) {
+ /* R0 and R1 */
+ uECC_word_t Rx[2][uECC_MAX_WORDS];
+ uECC_word_t Ry[2][uECC_MAX_WORDS];
+ uECC_word_t z[uECC_MAX_WORDS];
+ bitcount_t i;
+ uECC_word_t nb;
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_set(Rx[1], point, num_words);
+ uECC_vli_set(Ry[1], point + num_words, num_words);
+
+ XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
+
+ for (i = num_bits - 2; i > 0; --i) {
+ nb = !uECC_vli_testBit(scalar, i);
+ XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+ XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+ }
+
+ nb = !uECC_vli_testBit(scalar, 0);
+ XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+
+ /* Find final 1/Z value. */
+ uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
+ uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
+ uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
+ uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0)) */
+ /* yP / (xP * Yb * (X1 - X0)) */
+ uECC_vli_modMult_fast(z, z, point + num_words, curve);
+ uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */
+ /* End 1/Z calculation */
+
+ XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+ apply_z(Rx[0], Ry[0], z, curve);
+
+ uECC_vli_set(result, Rx[0], num_words);
+ uECC_vli_set(result + num_words, Ry[0], num_words);
+}
+
+static uECC_word_t regularize_k(const uECC_word_t * const k,
+ uECC_word_t *k0,
+ uECC_word_t *k1,
+ uECC_Curve curve) {
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+ bitcount_t num_n_bits = curve->num_n_bits;
+ uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
+ (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
+ uECC_vli_testBit(k0, num_n_bits));
+ uECC_vli_add(k1, k0, curve->n, num_n_words);
+ return carry;
+}
+
+static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+ uECC_word_t *private_key,
+ uECC_Curve curve) {
+ uECC_word_t tmp1[uECC_MAX_WORDS];
+ uECC_word_t tmp2[uECC_MAX_WORDS];
+ uECC_word_t *p2[2] = {tmp1, tmp2};
+ uECC_word_t carry;
+
+ /* Regularize the bitcount for the private key so that attackers cannot use a side channel
+ attack to learn the number of leading zeros. */
+ carry = regularize_k(private_key, tmp1, tmp2, curve);
+
+ EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
+
+ if (EccPoint_isZero(result, curve)) {
+ return 0;
+ }
+ return 1;
+}
+
+#if uECC_WORD_SIZE == 1
+
+uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
+ int num_bytes,
+ const uint8_t *native) {
+ wordcount_t i;
+ for (i = 0; i < num_bytes; ++i) {
+ bytes[i] = native[(num_bytes - 1) - i];
+ }
+}
+
+uECC_VLI_API void uECC_vli_bytesToNative(uint8_t *native,
+ const uint8_t *bytes,
+ int num_bytes) {
+ uECC_vli_nativeToBytes(native, num_bytes, bytes);
+}
+
+#else
+
+uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
+ int num_bytes,
+ const uECC_word_t *native) {
+ wordcount_t i;
+ for (i = 0; i < num_bytes; ++i) {
+ unsigned b = num_bytes - 1 - i;
+ bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
+ }
+}
+
+uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
+ const uint8_t *bytes,
+ int num_bytes) {
+ wordcount_t i;
+ uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
+ for (i = 0; i < num_bytes; ++i) {
+ unsigned b = num_bytes - 1 - i;
+ native[b / uECC_WORD_SIZE] |=
+ (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
+ }
+}
+
+#endif /* uECC_WORD_SIZE */
+
+/* Generates a random integer in the range 0 < random < top.
+ Both random and top have num_words words. */
+uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
+ const uECC_word_t *top,
+ wordcount_t num_words) {
+ uECC_word_t mask = (uECC_word_t)-1;
+ uECC_word_t tries;
+ bitcount_t num_bits = uECC_vli_numBits(top, num_words);
+
+ if (!g_rng_function) {
+ return 0;
+ }
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
+ return 0;
+ }
+ random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
+ if (!uECC_vli_isZero(random, num_words) &&
+ uECC_vli_cmp(top, random, num_words) == 1) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int uECC_make_key(uint8_t *public_key,
+ uint8_t *private_key,
+ uECC_Curve curve) {
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ uECC_word_t *_private = (uECC_word_t *)private_key;
+ uECC_word_t *_public = (uECC_word_t *)public_key;
+#else
+ uECC_word_t _private[uECC_MAX_WORDS];
+ uECC_word_t _public[uECC_MAX_WORDS * 2];
+#endif
+ uECC_word_t tries;
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ if (!uECC_generate_random_int(_private, curve->n, BITS_TO_WORDS(curve->num_n_bits))) {
+ return 0;
+ }
+
+ if (EccPoint_compute_public_key(_public, _private, curve)) {
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
+ uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits), _private);
+ uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
+ uECC_vli_nativeToBytes(
+ public_key + curve->num_bytes, curve->num_bytes, _public + curve->num_words);
+#endif
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int uECC_shared_secret(const uint8_t *public_key,
+ const uint8_t *private_key,
+ uint8_t *secret,
+ uECC_Curve curve) {
+ uECC_word_t _public[uECC_MAX_WORDS * 2];
+ uECC_word_t _private[uECC_MAX_WORDS];
+
+ uECC_word_t tmp[uECC_MAX_WORDS];
+ uECC_word_t *p2[2] = {_private, tmp};
+ uECC_word_t *initial_Z = 0;
+ uECC_word_t carry;
+ wordcount_t num_words = curve->num_words;
+ wordcount_t num_bytes = curve->num_bytes;
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy((uint8_t *) _private, private_key, num_bytes);
+ bcopy((uint8_t *) _public, public_key, num_bytes*2);
+#else
+ uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits));
+ uECC_vli_bytesToNative(_public, public_key, num_bytes);
+ uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes);
+#endif
+
+ /* Regularize the bitcount for the private key so that attackers cannot use a side channel
+ attack to learn the number of leading zeros. */
+ carry = regularize_k(_private, _private, tmp, curve);
+
+ /* If an RNG function was specified, try to get a random initial Z value to improve
+ protection against side-channel attacks. */
+ if (g_rng_function) {
+ if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
+ return 0;
+ }
+ initial_Z = p2[carry];
+ }
+
+ EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve);
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy((uint8_t *) secret, (uint8_t *) _public, num_bytes);
+#else
+ uECC_vli_nativeToBytes(secret, num_bytes, _public);
+#endif
+ return !EccPoint_isZero(_public, curve);
+}
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve) {
+ wordcount_t i;
+ for (i = 0; i < curve->num_bytes; ++i) {
+ compressed[i+1] = public_key[i];
+ }
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ compressed[0] = 2 + (public_key[curve->num_bytes] & 0x01);
+#else
+ compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01);
+#endif
+}
+
+void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) {
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ uECC_word_t *point = (uECC_word_t *)public_key;
+#else
+ uECC_word_t point[uECC_MAX_WORDS * 2];
+#endif
+ uECC_word_t *y = point + curve->num_words;
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy(public_key, compressed+1, curve->num_bytes);
+#else
+ uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes);
+#endif
+ curve->x_side(y, point, curve);
+ curve->mod_sqrt(y, curve);
+
+ if ((y[0] & 0x01) != (compressed[0] & 0x01)) {
+ uECC_vli_sub(y, curve->p, y, curve->num_words);
+ }
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
+ uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
+ uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
+#endif
+}
+#endif /* uECC_SUPPORT_COMPRESSED_POINT */
+
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
+ uECC_word_t tmp1[uECC_MAX_WORDS];
+ uECC_word_t tmp2[uECC_MAX_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ /* The point at infinity is invalid. */
+ if (EccPoint_isZero(point, curve)) {
+ return 0;
+ }
+
+ /* x and y must be smaller than p. */
+ if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
+ uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
+ return 0;
+ }
+
+ uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
+ curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
+
+ /* Make sure that y^2 == x^3 + ax + b */
+ return (int)(uECC_vli_equal(tmp1, tmp2, num_words));
+}
+
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) {
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ uECC_word_t *_public = (uECC_word_t *)public_key;
+#else
+ uECC_word_t _public[uECC_MAX_WORDS * 2];
+#endif
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
+ uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+ uECC_vli_bytesToNative(
+ _public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes);
+#endif
+ return uECC_valid_point(_public, curve);
+}
+
+int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) {
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ uECC_word_t *_private = (uECC_word_t *)private_key;
+ uECC_word_t *_public = (uECC_word_t *)public_key;
+#else
+ uECC_word_t _private[uECC_MAX_WORDS];
+ uECC_word_t _public[uECC_MAX_WORDS * 2];
+#endif
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
+ uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits));
+#endif
+
+ /* Make sure the private key is in the range [1, n-1]. */
+ if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
+ return 0;
+ }
+
+ if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
+ return 0;
+ }
+
+ /* Compute public key. */
+ if (!EccPoint_compute_public_key(_public, _private, curve)) {
+ return 0;
+ }
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
+ uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
+ uECC_vli_nativeToBytes(
+ public_key + curve->num_bytes, curve->num_bytes, _public + curve->num_words);
+#endif
+ return 1;
+}
+
+
+/* -------- ECDSA code -------- */
+
+static void bits2int(uECC_word_t *native,
+ const uint8_t *bits,
+ unsigned bits_size,
+ uECC_Curve curve) {
+ unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
+ unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+ int shift;
+ uECC_word_t carry;
+ uECC_word_t *ptr;
+
+ if (bits_size > num_n_bytes) {
+ bits_size = num_n_bytes;
+ }
+
+ uECC_vli_clear(native, num_n_words);
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy((uint8_t *) native, bits, bits_size);
+#else
+ uECC_vli_bytesToNative(native, bits, bits_size);
+#endif
+ if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
+ return;
+ }
+ shift = bits_size * 8 - curve->num_n_bits;
+ carry = 0;
+ ptr = native + num_n_words;
+ while (ptr-- > native) {
+ uECC_word_t temp = *ptr;
+ *ptr = (temp >> shift) | carry;
+ carry = temp << (uECC_WORD_BITS - shift);
+ }
+
+ /* Reduce mod curve_n */
+ if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
+ uECC_vli_sub(native, native, curve->n, num_n_words);
+ }
+}
+
+static int uECC_sign_with_k(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ uECC_word_t *k,
+ uint8_t *signature,
+ uECC_Curve curve) {
+
+ uECC_word_t tmp[uECC_MAX_WORDS];
+ uECC_word_t s[uECC_MAX_WORDS];
+ uECC_word_t *k2[2] = {tmp, s};
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ uECC_word_t *p = (uECC_word_t *)signature;
+#else
+ uECC_word_t p[uECC_MAX_WORDS * 2];
+#endif
+ uECC_word_t carry;
+ wordcount_t num_words = curve->num_words;
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+ bitcount_t num_n_bits = curve->num_n_bits;
+
+ /* Make sure 0 < k < curve_n */
+ if (uECC_vli_isZero(k, num_words) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
+ return 0;
+ }
+
+ carry = regularize_k(k, tmp, s, curve);
+ EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
+ if (uECC_vli_isZero(p, num_words)) {
+ return 0;
+ }
+
+ /* If an RNG function was specified, get a random number
+ to prevent side channel analysis of k. */
+ if (!g_rng_function) {
+ uECC_vli_clear(tmp, num_n_words);
+ tmp[0] = 1;
+ } else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
+ return 0;
+ }
+
+ /* Prevent side channel analysis of uECC_vli_modInv() to determine
+ bits of k / the private key by premultiplying by a random number */
+ uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
+ uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
+ uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0
+ uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
+#endif
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy((uint8_t *) tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
+#else
+ uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); /* tmp = d */
+#endif
+
+ s[num_n_words - 1] = 0;
+ uECC_vli_set(s, p, num_words);
+ uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
+
+ bits2int(tmp, message_hash, hash_size, curve);
+ uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
+ uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
+ if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
+ return 0;
+ }
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes);
+#else
+ uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
+#endif
+ return 1;
+}
+
+int uECC_sign(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ uint8_t *signature,
+ uECC_Curve curve) {
+ uECC_word_t k[uECC_MAX_WORDS];
+ uECC_word_t tries;
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ if (!uECC_generate_random_int(k, curve->n, BITS_TO_WORDS(curve->num_n_bits))) {
+ return 0;
+ }
+
+ if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
+ the same size as the hash result size. */
+static void HMAC_init(const uECC_HashContext *hash_context, const uint8_t *K) {
+ uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
+ unsigned i;
+ for (i = 0; i < hash_context->result_size; ++i)
+ pad[i] = K[i] ^ 0x36;
+ for (; i < hash_context->block_size; ++i)
+ pad[i] = 0x36;
+
+ hash_context->init_hash(hash_context);
+ hash_context->update_hash(hash_context, pad, hash_context->block_size);
+}
+
+static void HMAC_update(const uECC_HashContext *hash_context,
+ const uint8_t *message,
+ unsigned message_size) {
+ hash_context->update_hash(hash_context, message, message_size);
+}
+
+static void HMAC_finish(const uECC_HashContext *hash_context,
+ const uint8_t *K,
+ uint8_t *result) {
+ uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
+ unsigned i;
+ for (i = 0; i < hash_context->result_size; ++i)
+ pad[i] = K[i] ^ 0x5c;
+ for (; i < hash_context->block_size; ++i)
+ pad[i] = 0x5c;
+
+ hash_context->finish_hash(hash_context, result);
+
+ hash_context->init_hash(hash_context);
+ hash_context->update_hash(hash_context, pad, hash_context->block_size);
+ hash_context->update_hash(hash_context, result, hash_context->result_size);
+ hash_context->finish_hash(hash_context, result);
+}
+
+/* V = HMAC_K(V) */
+static void update_V(const uECC_HashContext *hash_context, uint8_t *K, uint8_t *V) {
+ HMAC_init(hash_context, K);
+ HMAC_update(hash_context, V, hash_context->result_size);
+ HMAC_finish(hash_context, K, V);
+}
+
+/* Deterministic signing, similar to RFC 6979. Differences are:
+ * We just use H(m) directly rather than bits2octets(H(m))
+ (it is not reduced modulo curve_n).
+ * We generate a value for k (aka T) directly rather than converting endianness.
+
+ Layout of hash_context->tmp: <K> | <V> | (1 byte overlapped 0x00 or 0x01) / <HMAC pad> */
+int uECC_sign_deterministic(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ const uECC_HashContext *hash_context,
+ uint8_t *signature,
+ uECC_Curve curve) {
+ uint8_t *K = hash_context->tmp;
+ uint8_t *V = K + hash_context->result_size;
+ wordcount_t num_bytes = curve->num_bytes;
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+ bitcount_t num_n_bits = curve->num_n_bits;
+ uECC_word_t tries;
+ unsigned i;
+ for (i = 0; i < hash_context->result_size; ++i) {
+ V[i] = 0x01;
+ K[i] = 0;
+ }
+
+ /* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */
+ HMAC_init(hash_context, K);
+ V[hash_context->result_size] = 0x00;
+ HMAC_update(hash_context, V, hash_context->result_size + 1);
+ HMAC_update(hash_context, private_key, num_bytes);
+ HMAC_update(hash_context, message_hash, hash_size);
+ HMAC_finish(hash_context, K, K);
+
+ update_V(hash_context, K, V);
+
+ /* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */
+ HMAC_init(hash_context, K);
+ V[hash_context->result_size] = 0x01;
+ HMAC_update(hash_context, V, hash_context->result_size + 1);
+ HMAC_update(hash_context, private_key, num_bytes);
+ HMAC_update(hash_context, message_hash, hash_size);
+ HMAC_finish(hash_context, K, K);
+
+ update_V(hash_context, K, V);
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ uECC_word_t T[uECC_MAX_WORDS];
+ uint8_t *T_ptr = (uint8_t *)T;
+ wordcount_t T_bytes = 0;
+ for (;;) {
+ update_V(hash_context, K, V);
+ for (i = 0; i < hash_context->result_size; ++i) {
+ T_ptr[T_bytes++] = V[i];
+ if (T_bytes >= num_n_words * uECC_WORD_SIZE) {
+ goto filled;
+ }
+ }
+ }
+ filled:
+ if ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8 > num_n_bits) {
+ uECC_word_t mask = (uECC_word_t)-1;
+ T[num_n_words - 1] &=
+ mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits));
+ }
+
+ if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) {
+ return 1;
+ }
+
+ /* K = HMAC_K(V || 0x00) */
+ HMAC_init(hash_context, K);
+ V[hash_context->result_size] = 0x00;
+ HMAC_update(hash_context, V, hash_context->result_size + 1);
+ HMAC_finish(hash_context, K, K);
+
+ update_V(hash_context, K, V);
+ }
+ return 0;
+}
+
+static bitcount_t smax(bitcount_t a, bitcount_t b) {
+ return (a > b ? a : b);
+}
+
+int uECC_verify(const uint8_t *public_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ const uint8_t *signature,
+ uECC_Curve curve) {
+ uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
+ uECC_word_t z[uECC_MAX_WORDS];
+ uECC_word_t sum[uECC_MAX_WORDS * 2];
+ uECC_word_t rx[uECC_MAX_WORDS];
+ uECC_word_t ry[uECC_MAX_WORDS];
+ uECC_word_t tx[uECC_MAX_WORDS];
+ uECC_word_t ty[uECC_MAX_WORDS];
+ uECC_word_t tz[uECC_MAX_WORDS];
+ const uECC_word_t *points[4];
+ const uECC_word_t *point;
+ bitcount_t num_bits;
+ bitcount_t i;
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ uECC_word_t *_public = (uECC_word_t *)public_key;
+#else
+ uECC_word_t _public[uECC_MAX_WORDS * 2];
+#endif
+ uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
+ wordcount_t num_words = curve->num_words;
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+ rx[num_n_words - 1] = 0;
+ r[num_n_words - 1] = 0;
+ s[num_n_words - 1] = 0;
+
+#if uECC_VLI_NATIVE_LITTLE_ENDIAN
+ bcopy((uint8_t *) r, signature, curve->num_bytes);
+ bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes);
+#else
+ uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+ uECC_vli_bytesToNative(
+ _public + num_words, public_key + curve->num_bytes, curve->num_bytes);
+ uECC_vli_bytesToNative(r, signature, curve->num_bytes);
+ uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
+#endif
+
+ /* r, s must not be 0. */
+ if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
+ return 0;
+ }
+
+ /* r, s must be < n. */
+ if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
+ uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
+ return 0;
+ }
+
+ /* Calculate u1 and u2. */
+ uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
+ u1[num_n_words - 1] = 0;
+ bits2int(u1, message_hash, hash_size, curve);
+ uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
+ uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
+
+ /* Calculate sum = G + Q. */
+ uECC_vli_set(sum, _public, num_words);
+ uECC_vli_set(sum + num_words, _public + num_words, num_words);
+ uECC_vli_set(tx, curve->G, num_words);
+ uECC_vli_set(ty, curve->G + num_words, num_words);
+ uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
+ XYcZ_add(tx, ty, sum, sum + num_words, curve);
+ uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
+ apply_z(sum, sum + num_words, z, curve);
+
+ /* Use Shamir's trick to calculate u1*G + u2*Q */
+ points[0] = 0;
+ points[1] = curve->G;
+ points[2] = _public;
+ points[3] = sum;
+ num_bits = smax(uECC_vli_numBits(u1, num_n_words),
+ uECC_vli_numBits(u2, num_n_words));
+
+ point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
+ ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
+ uECC_vli_set(rx, point, num_words);
+ uECC_vli_set(ry, point + num_words, num_words);
+ uECC_vli_clear(z, num_words);
+ z[0] = 1;
+
+ for (i = num_bits - 2; i >= 0; --i) {
+ uECC_word_t index;
+ curve->double_jacobian(rx, ry, z, curve);
+
+ index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
+ point = points[index];
+ if (point) {
+ uECC_vli_set(tx, point, num_words);
+ uECC_vli_set(ty, point + num_words, num_words);
+ apply_z(tx, ty, z, curve);
+ uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
+ XYcZ_add(tx, ty, rx, ry, curve);
+ uECC_vli_modMult_fast(z, z, tz, curve);
+ }
+ }
+
+ uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
+ apply_z(rx, ry, z, curve);
+
+ /* v = x1 (mod n) */
+ if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
+ uECC_vli_sub(rx, rx, curve->n, num_n_words);
+ }
+
+ /* Accept only if v == r. */
+ return (int)(uECC_vli_equal(rx, r, num_words));
+}
+
+#if uECC_ENABLE_VLI_API
+
+unsigned uECC_curve_num_words(uECC_Curve curve) {
+ return curve->num_words;
+}
+
+unsigned uECC_curve_num_bytes(uECC_Curve curve) {
+ return curve->num_bytes;
+}
+
+unsigned uECC_curve_num_bits(uECC_Curve curve) {
+ return curve->num_bytes * 8;
+}
+
+unsigned uECC_curve_num_n_words(uECC_Curve curve) {
+ return BITS_TO_WORDS(curve->num_n_bits);
+}
+
+unsigned uECC_curve_num_n_bytes(uECC_Curve curve) {
+ return BITS_TO_BYTES(curve->num_n_bits);
+}
+
+unsigned uECC_curve_num_n_bits(uECC_Curve curve) {
+ return curve->num_n_bits;
+}
+
+const uECC_word_t *uECC_curve_p(uECC_Curve curve) {
+ return curve->p;
+}
+
+const uECC_word_t *uECC_curve_n(uECC_Curve curve) {
+ return curve->n;
+}
+
+const uECC_word_t *uECC_curve_G(uECC_Curve curve) {
+ return curve->G;
+}
+
+const uECC_word_t *uECC_curve_b(uECC_Curve curve) {
+ return curve->b;
+}
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve) {
+ curve->mod_sqrt(a, curve);
+}
+#endif
+
+void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve) {
+#if (uECC_OPTIMIZATION_LEVEL > 0)
+ curve->mmod_fast(result, product);
+#else
+ uECC_vli_mmod(result, product, curve->p, curve->num_words);
+#endif
+}
+
+void uECC_point_mult(uECC_word_t *result,
+ const uECC_word_t *point,
+ const uECC_word_t *scalar,
+ uECC_Curve curve) {
+ uECC_word_t tmp1[uECC_MAX_WORDS];
+ uECC_word_t tmp2[uECC_MAX_WORDS];
+ uECC_word_t *p2[2] = {tmp1, tmp2};
+ uECC_word_t carry = regularize_k(scalar, tmp1, tmp2, curve);
+
+ EccPoint_mult(result, point, p2[!carry], 0, curve->num_n_bits + 1, curve);
+}
+
+#endif /* uECC_ENABLE_VLI_API */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.h b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.h
new file mode 100644
index 00000000..99117631
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC.h
@@ -0,0 +1,362 @@
+/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_H_
+#define _UECC_H_
+
+#include <stdint.h>
+
+/* Platform selection options.
+If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros.
+Possible values for uECC_PLATFORM are defined below: */
+#define uECC_arch_other 0
+#define uECC_x86 1
+#define uECC_x86_64 2
+#define uECC_arm 3
+#define uECC_arm_thumb 4
+#define uECC_arm_thumb2 5
+#define uECC_arm64 6
+#define uECC_avr 7
+
+/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
+If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
+platform. */
+
+/* Optimization level; trade speed for code size.
+ Larger values produce code that is faster but larger.
+ Currently supported values are 0 - 4; 0 is unusably slow for most applications.
+ Optimization level 4 currently only has an effect ARM platforms where more than one
+ curve is enabled. */
+#ifndef uECC_OPTIMIZATION_LEVEL
+ #define uECC_OPTIMIZATION_LEVEL 2
+#endif
+
+/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
+used for (scalar) squaring instead of the generic multiplication function. This can make things
+faster somewhat faster, but increases the code size. */
+#ifndef uECC_SQUARE_FUNC
+ #define uECC_SQUARE_FUNC 0
+#endif
+
+/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native
+little-endian format for *all* arrays passed in and out of the public API. This includes public
+and private keys, shared secrets, signatures and message hashes.
+Using this switch reduces the amount of call stack memory used by uECC, since less intermediate
+translations are required.
+Note that this will *only* work on native little-endian processors and it will treat the uint8_t
+arrays passed into the public API as word arrays, therefore requiring the provided byte arrays
+to be word aligned on architectures that do not support unaligned accesses. */
+#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN
+ #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0
+#endif
+
+/* Curve support selection. Set to 0 to remove that curve. */
+#ifndef uECC_SUPPORTS_secp160r1
+ #define uECC_SUPPORTS_secp160r1 1
+#endif
+#ifndef uECC_SUPPORTS_secp192r1
+ #define uECC_SUPPORTS_secp192r1 1
+#endif
+#ifndef uECC_SUPPORTS_secp224r1
+ #define uECC_SUPPORTS_secp224r1 1
+#endif
+#ifndef uECC_SUPPORTS_secp256r1
+ #define uECC_SUPPORTS_secp256r1 1
+#endif
+#ifndef uECC_SUPPORTS_secp256k1
+ #define uECC_SUPPORTS_secp256k1 1
+#endif
+
+/* Specifies whether compressed point format is supported.
+ Set to 0 to disable point compression/decompression functions. */
+#ifndef uECC_SUPPORT_COMPRESSED_POINT
+ #define uECC_SUPPORT_COMPRESSED_POINT 1
+#endif
+
+struct uECC_Curve_t;
+typedef const struct uECC_Curve_t * uECC_Curve;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if uECC_SUPPORTS_secp160r1
+uECC_Curve uECC_secp160r1(void);
+#endif
+#if uECC_SUPPORTS_secp192r1
+uECC_Curve uECC_secp192r1(void);
+#endif
+#if uECC_SUPPORTS_secp224r1
+uECC_Curve uECC_secp224r1(void);
+#endif
+#if uECC_SUPPORTS_secp256r1
+uECC_Curve uECC_secp256r1(void);
+#endif
+#if uECC_SUPPORTS_secp256k1
+uECC_Curve uECC_secp256k1(void);
+#endif
+
+/* uECC_RNG_Function type
+The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if
+'dest' was filled with random data, or 0 if the random data could not be generated.
+The filled-in values should be either truly random, or from a cryptographically-secure PRNG.
+
+A correctly functioning RNG function must be set (using uECC_set_rng()) before calling
+uECC_make_key() or uECC_sign().
+
+Setting a correctly functioning RNG function improves the resistance to side-channel attacks
+for uECC_shared_secret() and uECC_sign_deterministic().
+
+A correct RNG function is set by default when building for Windows, Linux, or OS X.
+If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom,
+you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined
+RNG function; you must provide your own.
+*/
+typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size);
+
+/* uECC_set_rng() function.
+Set the function that will be used to generate random bytes. The RNG function should
+return 1 if the random data was generated, or 0 if the random data could not be generated.
+
+On platforms where there is no predefined RNG function (eg embedded platforms), this must
+be called before uECC_make_key() or uECC_sign() are used.
+
+Inputs:
+ rng_function - The function that will be used to generate random bytes.
+*/
+void uECC_set_rng(uECC_RNG_Function rng_function);
+
+/* uECC_get_rng() function.
+
+Returns the function that will be used to generate random bytes.
+*/
+uECC_RNG_Function uECC_get_rng(void);
+
+/* uECC_curve_private_key_size() function.
+
+Returns the size of a private key for the curve in bytes.
+*/
+int uECC_curve_private_key_size(uECC_Curve curve);
+
+/* uECC_curve_public_key_size() function.
+
+Returns the size of a public key for the curve in bytes.
+*/
+int uECC_curve_public_key_size(uECC_Curve curve);
+
+/* uECC_make_key() function.
+Create a public/private key pair.
+
+Outputs:
+ public_key - Will be filled in with the public key. Must be at least 2 * the curve size
+ (in bytes) long. For example, if the curve is secp256r1, public_key must be 64
+ bytes long.
+ private_key - Will be filled in with the private key. Must be as long as the curve order; this
+ is typically the same as the curve size, except for secp160r1. For example, if the
+ curve is secp256r1, private_key must be 32 bytes long.
+
+ For secp160r1, private_key must be 21 bytes long! Note that the first byte will
+ almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero).
+
+Returns 1 if the key pair was generated successfully, 0 if an error occurred.
+*/
+int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve);
+
+/* uECC_shared_secret() function.
+Compute a shared secret given your secret key and someone else's public key.
+Note: It is recommended that you hash the result of uECC_shared_secret() before using it for
+symmetric encryption or HMAC.
+
+Inputs:
+ public_key - The public key of the remote party.
+ private_key - Your private key.
+
+Outputs:
+ secret - Will be filled in with the shared secret value. Must be the same size as the
+ curve size; for example, if the curve is secp256r1, secret must be 32 bytes long.
+
+Returns 1 if the shared secret was generated successfully, 0 if an error occurred.
+*/
+int uECC_shared_secret(const uint8_t *public_key,
+ const uint8_t *private_key,
+ uint8_t *secret,
+ uECC_Curve curve);
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+/* uECC_compress() function.
+Compress a public key.
+
+Inputs:
+ public_key - The public key to compress.
+
+Outputs:
+ compressed - Will be filled in with the compressed public key. Must be at least
+ (curve size + 1) bytes long; for example, if the curve is secp256r1,
+ compressed must be 33 bytes long.
+*/
+void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve);
+
+/* uECC_decompress() function.
+Decompress a compressed public key.
+
+Inputs:
+ compressed - The compressed public key.
+
+Outputs:
+ public_key - Will be filled in with the decompressed public key.
+*/
+void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve);
+#endif /* uECC_SUPPORT_COMPRESSED_POINT */
+
+/* uECC_valid_public_key() function.
+Check to see if a public key is valid.
+
+Note that you are not required to check for a valid public key before using any other uECC
+functions. However, you may wish to avoid spending CPU time computing a shared secret or
+verifying a signature using an invalid public key.
+
+Inputs:
+ public_key - The public key to check.
+
+Returns 1 if the public key is valid, 0 if it is invalid.
+*/
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
+
+/* uECC_compute_public_key() function.
+Compute the corresponding public key for a private key.
+
+Inputs:
+ private_key - The private key to compute the public key for
+
+Outputs:
+ public_key - Will be filled in with the corresponding public key
+
+Returns 1 if the key was computed successfully, 0 if an error occurred.
+*/
+int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);
+
+/* uECC_sign() function.
+Generate an ECDSA signature for a given hash value.
+
+Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
+this function along with your private key.
+
+Inputs:
+ private_key - Your private key.
+ message_hash - The hash of the message to sign.
+ hash_size - The size of message_hash in bytes.
+
+Outputs:
+ signature - Will be filled in with the signature value. Must be at least 2 * curve size long.
+ For example, if the curve is secp256r1, signature must be 64 bytes long.
+
+Returns 1 if the signature generated successfully, 0 if an error occurred.
+*/
+int uECC_sign(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ uint8_t *signature,
+ uECC_Curve curve);
+
+/* uECC_HashContext structure.
+This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
+The structure will be used for multiple hash computations; each time a new hash
+is computed, init_hash() will be called, followed by one or more calls to
+update_hash(), and finally a call to finish_hash() to produce the resulting hash.
+
+The intention is that you will create a structure that includes uECC_HashContext
+followed by any hash-specific data. For example:
+
+typedef struct SHA256_HashContext {
+ uECC_HashContext uECC;
+ SHA256_CTX ctx;
+} SHA256_HashContext;
+
+void init_SHA256(uECC_HashContext *base) {
+ SHA256_HashContext *context = (SHA256_HashContext *)base;
+ SHA256_Init(&context->ctx);
+}
+
+void update_SHA256(uECC_HashContext *base,
+ const uint8_t *message,
+ unsigned message_size) {
+ SHA256_HashContext *context = (SHA256_HashContext *)base;
+ SHA256_Update(&context->ctx, message, message_size);
+}
+
+void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
+ SHA256_HashContext *context = (SHA256_HashContext *)base;
+ SHA256_Final(hash_result, &context->ctx);
+}
+
+... when signing ...
+{
+ uint8_t tmp[32 + 32 + 64];
+ SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
+ uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
+}
+*/
+typedef struct uECC_HashContext {
+ void (*init_hash)(const struct uECC_HashContext *context);
+ void (*update_hash)(const struct uECC_HashContext *context,
+ const uint8_t *message,
+ unsigned message_size);
+ void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result);
+ unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
+ unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
+ uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
+} uECC_HashContext;
+
+/* uECC_sign_deterministic() function.
+Generate an ECDSA signature for a given hash value, using a deterministic algorithm
+(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling
+this function; however, if the RNG is defined it will improve resistance to side-channel
+attacks.
+
+Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to
+this function along with your private key and a hash context. Note that the message_hash
+does not need to be computed with the same hash function used by hash_context.
+
+Inputs:
+ private_key - Your private key.
+ message_hash - The hash of the message to sign.
+ hash_size - The size of message_hash in bytes.
+ hash_context - A hash context to use.
+
+Outputs:
+ signature - Will be filled in with the signature value.
+
+Returns 1 if the signature generated successfully, 0 if an error occurred.
+*/
+int uECC_sign_deterministic(const uint8_t *private_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ const uECC_HashContext *hash_context,
+ uint8_t *signature,
+ uECC_Curve curve);
+
+/* uECC_verify() function.
+Verify an ECDSA signature.
+
+Usage: Compute the hash of the signed data using the same hash as the signer and
+pass it to this function along with the signer's public key and the signature values (r and s).
+
+Inputs:
+ public_key - The signer's public key.
+ message_hash - The hash of the signed data.
+ hash_size - The size of message_hash in bytes.
+ signature - The signature value.
+
+Returns 1 if the signature is valid, 0 if it is invalid.
+*/
+int uECC_verify(const uint8_t *public_key,
+ const uint8_t *message_hash,
+ unsigned hash_size,
+ const uint8_t *signature,
+ uECC_Curve curve);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _UECC_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC_vli.h b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC_vli.h
new file mode 100644
index 00000000..864cc333
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/deps/micro-ecc/uECC_vli.h
@@ -0,0 +1,172 @@
+/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
+
+#ifndef _UECC_VLI_H_
+#define _UECC_VLI_H_
+
+#include "uECC.h"
+#include "types.h"
+
+/* Functions for raw large-integer manipulation. These are only available
+ if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */
+#ifndef uECC_ENABLE_VLI_API
+ #define uECC_ENABLE_VLI_API 0
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if uECC_ENABLE_VLI_API
+
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
+
+/* Constant-time comparison to zero - secure way to compare long integers */
+/* Returns 1 if vli == 0, 0 otherwise. */
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
+
+/* Returns nonzero if bit 'bit' of vli is set. */
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
+
+/* Counts the number of bits required to represent vli. */
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words);
+
+/* Sets dest = src. */
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words);
+
+/* Constant-time comparison function - secure way to compare long integers */
+/* Returns one if left == right, zero otherwise */
+uECC_word_t uECC_vli_equal(const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words);
+
+/* Constant-time comparison function - secure way to compare long integers */
+/* Returns sign of left - right, in constant time. */
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words);
+
+/* Computes vli = vli >> 1. */
+void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words);
+
+/* Computes result = left + right, returning carry. Can modify in place. */
+uECC_word_t uECC_vli_add(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words);
+
+/* Computes result = left - right, returning borrow. Can modify in place. */
+uECC_word_t uECC_vli_sub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words);
+
+/* Computes result = left * right. Result must be 2 * num_words long. */
+void uECC_vli_mult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words);
+
+/* Computes result = left^2. Result must be 2 * num_words long. */
+void uECC_vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words);
+
+/* Computes result = (left + right) % mod.
+ Assumes that left < mod and right < mod, and that result does not overlap mod. */
+void uECC_vli_modAdd(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/* Computes result = (left - right) % mod.
+ Assumes that left < mod and right < mod, and that result does not overlap mod. */
+void uECC_vli_modSub(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/* Computes result = product % mod, where product is 2N words long.
+ Currently only designed to work for mod == curve->p or curve_n. */
+void uECC_vli_mmod(uECC_word_t *result,
+ uECC_word_t *product,
+ const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/* Calculates result = product (mod curve->p), where product is up to
+ 2 * curve->num_words long. */
+void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve);
+
+/* Computes result = (left * right) % mod.
+ Currently only designed to work for mod == curve->p or curve_n. */
+void uECC_vli_modMult(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/* Computes result = (left * right) % curve->p. */
+void uECC_vli_modMult_fast(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *right,
+ uECC_Curve curve);
+
+/* Computes result = left^2 % mod.
+ Currently only designed to work for mod == curve->p or curve_n. */
+void uECC_vli_modSquare(uECC_word_t *result,
+ const uECC_word_t *left,
+ const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/* Computes result = left^2 % curve->p. */
+void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve);
+
+/* Computes result = (1 / input) % mod.*/
+void uECC_vli_modInv(uECC_word_t *result,
+ const uECC_word_t *input,
+ const uECC_word_t *mod,
+ wordcount_t num_words);
+
+#if uECC_SUPPORT_COMPRESSED_POINT
+/* Calculates a = sqrt(a) (mod curve->p) */
+void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve);
+#endif
+
+/* Converts an integer in uECC native format to big-endian bytes. */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native);
+/* Converts big-endian bytes to an integer in uECC native format. */
+void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes);
+
+unsigned uECC_curve_num_words(uECC_Curve curve);
+unsigned uECC_curve_num_bytes(uECC_Curve curve);
+unsigned uECC_curve_num_bits(uECC_Curve curve);
+unsigned uECC_curve_num_n_words(uECC_Curve curve);
+unsigned uECC_curve_num_n_bytes(uECC_Curve curve);
+unsigned uECC_curve_num_n_bits(uECC_Curve curve);
+
+const uECC_word_t *uECC_curve_p(uECC_Curve curve);
+const uECC_word_t *uECC_curve_n(uECC_Curve curve);
+const uECC_word_t *uECC_curve_G(uECC_Curve curve);
+const uECC_word_t *uECC_curve_b(uECC_Curve curve);
+
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
+
+/* Multiplies a point by a scalar. Points are represented by the X coordinate followed by
+ the Y coordinate in the same array, both coordinates are curve->num_words long. Note
+ that scalar must be curve->num_n_words long (NOT curve->num_words). */
+void uECC_point_mult(uECC_word_t *result,
+ const uECC_word_t *point,
+ const uECC_word_t *scalar,
+ uECC_Curve curve);
+
+/* Generates a random integer in the range 0 < random < top.
+ Both random and top have num_words words. */
+int uECC_generate_random_int(uECC_word_t *random,
+ const uECC_word_t *top,
+ wordcount_t num_words);
+
+#endif /* uECC_ENABLE_VLI_API */
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* _UECC_VLI_H_ */
diff --git a/web/server/h2o/libh2o/deps/picotls/include/picotls.h b/web/server/h2o/libh2o/deps/picotls/include/picotls.h
new file mode 100644
index 00000000..a862075f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/include/picotls.h
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef picotls_h
+#define picotls_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+#define PTLS_AES128_KEY_SIZE 16
+#define PTLS_AES256_KEY_SIZE 32
+#define PTLS_AES_IV_SIZE 16
+#define PTLS_AESGCM_IV_SIZE 12
+#define PTLS_AESGCM_TAG_SIZE 16
+
+#define PTLS_CHACHA20_KEY_SIZE 32
+#define PTLS_CHACHA20_IV_SIZE 16
+#define PTLS_CHACHA20POLY1305_IV_SIZE 12
+#define PTLS_CHACHA20POLY1305_TAG_SIZE 16
+
+#define PTLS_SHA256_BLOCK_SIZE 64
+#define PTLS_SHA256_DIGEST_SIZE 32
+
+#define PTLS_SHA384_BLOCK_SIZE 128
+#define PTLS_SHA384_DIGEST_SIZE 48
+
+#define PTLS_MAX_SECRET_SIZE 32
+#define PTLS_MAX_IV_SIZE 16
+#define PTLS_MAX_DIGEST_SIZE 64
+
+/* cipher-suites */
+#define PTLS_CIPHER_SUITE_AES_128_GCM_SHA256 0x1301
+#define PTLS_CIPHER_SUITE_AES_256_GCM_SHA384 0x1302
+#define PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 0x1303
+
+/* negotiated_groups */
+#define PTLS_GROUP_SECP256R1 23
+#define PTLS_GROUP_X25519 29
+
+/* signature algorithms */
+#define PTLS_SIGNATURE_RSA_PKCS1_SHA1 0x0201
+#define PTLS_SIGNATURE_RSA_PKCS1_SHA256 0x0401
+#define PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256 0x0403
+#define PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384 0x0503
+#define PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512 0x0603
+#define PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256 0x0804
+#define PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384 0x0805
+#define PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512 0x0806
+
+/* error classes and macros */
+#define PTLS_ERROR_CLASS_SELF_ALERT 0
+#define PTLS_ERROR_CLASS_PEER_ALERT 0x100
+#define PTLS_ERROR_CLASS_INTERNAL 0x200
+
+#define PTLS_ERROR_GET_CLASS(e) ((e) & ~0xff)
+#define PTLS_ALERT_TO_SELF_ERROR(e) ((e) + PTLS_ERROR_CLASS_SELF_ALERT)
+#define PTLS_ALERT_TO_PEER_ERROR(e) ((e) + PTLS_ERROR_CLASS_PEER_ALERT)
+#define PTLS_ERROR_TO_ALERT(e) ((e)&0xff)
+
+/* alerts */
+#define PTLS_ALERT_LEVEL_WARNING 1
+#define PTLS_ALERT_LEVEL_FATAL 2
+
+#define PTLS_ALERT_CLOSE_NOTIFY 0
+#define PTLS_ALERT_UNEXPECTED_MESSAGE 10
+#define PTLS_ALERT_BAD_RECORD_MAC 20
+#define PTLS_ALERT_HANDSHAKE_FAILURE 40
+#define PTLS_ALERT_BAD_CERTIFICATE 42
+#define PTLS_ALERT_CERTIFICATE_REVOKED 44
+#define PTLS_ALERT_CERTIFICATE_EXPIRED 45
+#define PTLS_ALERT_CERTIFICATE_UNKNOWN 46
+#define PTLS_ALERT_ILLEGAL_PARAMETER 47
+#define PTLS_ALERT_DECODE_ERROR 50
+#define PTLS_ALERT_DECRYPT_ERROR 51
+#define PTLS_ALERT_PROTOCOL_VERSION 70
+#define PTLS_ALERT_INTERNAL_ERROR 80
+#define PTLS_ALERT_USER_CANCELED 90
+#define PTLS_ALERT_MISSING_EXTENSION 109
+#define PTLS_ALERT_UNRECOGNIZED_NAME 112
+#define PTLS_ALERT_NO_APPLICATION_PROTOCOL 120
+
+/* internal errors */
+#define PTLS_ERROR_NO_MEMORY (PTLS_ERROR_CLASS_INTERNAL + 1)
+#define PTLS_ERROR_IN_PROGRESS (PTLS_ERROR_CLASS_INTERNAL + 2)
+#define PTLS_ERROR_LIBRARY (PTLS_ERROR_CLASS_INTERNAL + 3)
+#define PTLS_ERROR_INCOMPATIBLE_KEY (PTLS_ERROR_CLASS_INTERNAL + 4)
+#define PTLS_ERROR_SESSION_NOT_FOUND (PTLS_ERROR_CLASS_INTERNAL + 5)
+#define PTLS_ERROR_STATELESS_RETRY (PTLS_ERROR_CLASS_INTERNAL + 6)
+
+#define PTLS_ERROR_INCORRECT_BASE64 (PTLS_ERROR_CLASS_INTERNAL + 50)
+#define PTLS_ERROR_PEM_LABEL_NOT_FOUND (PTLS_ERROR_CLASS_INTERNAL + 51)
+#define PTLS_ERROR_BER_INCORRECT_ENCODING (PTLS_ERROR_CLASS_INTERNAL + 52)
+#define PTLS_ERROR_BER_MALFORMED_TYPE (PTLS_ERROR_CLASS_INTERNAL + 53)
+#define PTLS_ERROR_BER_MALFORMED_LENGTH (PTLS_ERROR_CLASS_INTERNAL + 54)
+#define PTLS_ERROR_BER_EXCESSIVE_LENGTH (PTLS_ERROR_CLASS_INTERNAL + 55)
+#define PTLS_ERROR_BER_ELEMENT_TOO_SHORT (PTLS_ERROR_CLASS_INTERNAL + 56)
+#define PTLS_ERROR_BER_UNEXPECTED_EOC (PTLS_ERROR_CLASS_INTERNAL + 57)
+#define PTLS_ERROR_DER_INDEFINITE_LENGTH (PTLS_ERROR_CLASS_INTERNAL + 58)
+#define PTLS_ERROR_INCORRECT_ASN1_SYNTAX (PTLS_ERROR_CLASS_INTERNAL + 59)
+#define PTLS_ERROR_INCORRECT_PEM_KEY_VERSION (PTLS_ERROR_CLASS_INTERNAL + 60)
+#define PTLS_ERROR_INCORRECT_PEM_ECDSA_KEY_VERSION (PTLS_ERROR_CLASS_INTERNAL + 61)
+#define PTLS_ERROR_INCORRECT_PEM_ECDSA_CURVE (PTLS_ERROR_CLASS_INTERNAL + 62)
+#define PTLS_ERROR_INCORRECT_PEM_ECDSA_KEYSIZE (PTLS_ERROR_CLASS_INTERNAL + 63)
+#define PTLS_ERROR_INCORRECT_ASN1_ECDSA_KEY_SYNTAX (PTLS_ERROR_CLASS_INTERNAL + 64)
+
+#define PTLS_ZERO_DIGEST_SHA256 \
+ { \
+ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, \
+ 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 \
+ }
+
+#define PTLS_ZERO_DIGEST_SHA384 \
+ { \
+ 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, \
+ 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, \
+ 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b \
+ }
+
+typedef struct st_ptls_t ptls_t;
+typedef struct st_ptls_context_t ptls_context_t;
+
+/**
+ * represents a sequence of octets
+ */
+typedef struct st_ptls_iovec_t {
+ uint8_t *base;
+ size_t len;
+} ptls_iovec_t;
+
+/**
+ * used for storing output
+ */
+typedef struct st_ptls_buffer_t {
+ uint8_t *base;
+ size_t capacity;
+ size_t off;
+ int is_allocated;
+} ptls_buffer_t;
+
+/**
+ * key exchange context built by ptls_key_exchange_algorithm::create.
+ */
+typedef struct st_ptls_key_exchange_context_t {
+ /**
+ * called once per created context. Callee must free resources allocated to the context and set *keyex to NULL. Secret and
+ * peerkey will be NULL in case the exchange never happened.
+ */
+ int (*on_exchange)(struct st_ptls_key_exchange_context_t **keyex, ptls_iovec_t *secret, ptls_iovec_t peerkey);
+} ptls_key_exchange_context_t;
+
+/**
+ * A key exchange algorithm.
+ */
+typedef const struct st_ptls_key_exchange_algorithm_t {
+ /**
+ * ID defined by the TLS specification
+ */
+ uint16_t id;
+ /**
+ * creates a context for asynchronous key exchange. The function is called when ClientHello is generated. The on_exchange
+ * callback of the created context is called when the client receives ServerHello.
+ */
+ int (*create)(ptls_key_exchange_context_t **ctx, ptls_iovec_t *pubkey);
+ /**
+ * implements synchronous key exchange. Called when receiving a ServerHello.
+ */
+ int (*exchange)(ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey);
+} ptls_key_exchange_algorithm_t;
+
+/**
+ * context of a symmetric cipher
+ */
+typedef struct st_ptls_cipher_context_t {
+ const struct st_ptls_cipher_algorithm_t *algo;
+ /* field above this line must not be altered by the crypto binding */
+ void (*do_dispose)(struct st_ptls_cipher_context_t *ctx);
+ void (*do_init)(struct st_ptls_cipher_context_t *ctx, const void *iv);
+ void (*do_transform)(struct st_ptls_cipher_context_t *ctx, void *output, const void *input, size_t len);
+} ptls_cipher_context_t;
+
+/**
+ * a symmetric cipher
+ */
+typedef const struct st_ptls_cipher_algorithm_t {
+ const char *name;
+ size_t key_size;
+ size_t iv_size;
+ size_t context_size;
+ int (*setup_crypto)(ptls_cipher_context_t *ctx, int is_enc, const void *key);
+} ptls_cipher_algorithm_t;
+
+/**
+ * AEAD context. AEAD implementations are allowed to stuff data at the end of the struct. The size of the memory allocated for the
+ * struct is governed by ptls_aead_algorithm_t::context_size.
+ */
+typedef struct st_ptls_aead_context_t {
+ const struct st_ptls_aead_algorithm_t *algo;
+ uint8_t static_iv[PTLS_MAX_IV_SIZE];
+ /* field above this line must not be altered by the crypto binding */
+ void (*dispose_crypto)(struct st_ptls_aead_context_t *ctx);
+ void (*do_encrypt_init)(struct st_ptls_aead_context_t *ctx, const void *iv, const void *aad, size_t aadlen);
+ size_t (*do_encrypt_update)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen);
+ size_t (*do_encrypt_final)(struct st_ptls_aead_context_t *ctx, void *output);
+ size_t (*do_decrypt)(struct st_ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, const void *iv,
+ const void *aad, size_t aadlen);
+} ptls_aead_context_t;
+
+/**
+ * An AEAD cipher.
+ */
+typedef const struct st_ptls_aead_algorithm_t {
+ /**
+ * name (following the convention of `openssl ciphers -v ALL`)
+ */
+ const char *name;
+ /**
+ * the underlying key stream
+ */
+ ptls_cipher_algorithm_t *ctr_cipher;
+ /**
+ * key size
+ */
+ size_t key_size;
+ /**
+ * size of the IV
+ */
+ size_t iv_size;
+ /**
+ * size of the tag
+ */
+ size_t tag_size;
+ /**
+ * size of memory allocated for ptls_aead_context_t. AEAD implementations can set this value to something greater than
+ * sizeof(ptls_aead_context_t) and stuff additional data at the bottom of the struct.
+ */
+ size_t context_size;
+ /**
+ * callback that sets up the crypto
+ */
+ int (*setup_crypto)(ptls_aead_context_t *ctx, int is_enc, const void *key);
+} ptls_aead_algorithm_t;
+
+/**
+ *
+ */
+typedef enum en_ptls_hash_final_mode_t {
+ /**
+ * obtains the digest and frees the context
+ */
+ PTLS_HASH_FINAL_MODE_FREE = 0,
+ /**
+ * obtains the digest and reset the context to initial state
+ */
+ PTLS_HASH_FINAL_MODE_RESET = 1,
+ /**
+ * obtains the digest while leaving the context as-is
+ */
+ PTLS_HASH_FINAL_MODE_SNAPSHOT = 2
+} ptls_hash_final_mode_t;
+
+/**
+ * A hash context.
+ */
+typedef struct st_ptls_hash_context_t {
+ /**
+ * feeds additional data into the hash context
+ */
+ void (*update)(struct st_ptls_hash_context_t *ctx, const void *src, size_t len);
+ /**
+ * returns the digest and performs necessary operation specified by mode
+ */
+ void (* final)(struct st_ptls_hash_context_t *ctx, void *md, ptls_hash_final_mode_t mode);
+ /**
+ * creates a copy of the hash context
+ */
+ struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src);
+} ptls_hash_context_t;
+
+/**
+ * A hash algorithm and its properties.
+ */
+typedef const struct st_ptls_hash_algorithm_t {
+ /**
+ * block size
+ */
+ size_t block_size;
+ /**
+ * digest size
+ */
+ size_t digest_size;
+ /**
+ * constructor that creates the hash context
+ */
+ ptls_hash_context_t *(*create)(void);
+ /**
+ * digest of zero-length octets
+ */
+ uint8_t empty_digest[PTLS_MAX_DIGEST_SIZE];
+} ptls_hash_algorithm_t;
+
+typedef const struct st_ptls_cipher_suite_t {
+ uint16_t id;
+ ptls_aead_algorithm_t *aead;
+ ptls_hash_algorithm_t *hash;
+} ptls_cipher_suite_t;
+
+#define PTLS_CALLBACK_TYPE0(ret, name) \
+ typedef struct st_ptls_##name##_t { \
+ ret (*cb)(struct st_ptls_##name##_t * self); \
+ } ptls_##name##_t
+
+#define PTLS_CALLBACK_TYPE(ret, name, ...) \
+ typedef struct st_ptls_##name##_t { \
+ ret (*cb)(struct st_ptls_##name##_t * self, __VA_ARGS__); \
+ } ptls_##name##_t
+
+/**
+ * returns current time in milliseconds (ptls_get_time can be used to return the physical time)
+ */
+PTLS_CALLBACK_TYPE0(uint64_t, get_time);
+/**
+ * after receiving ClientHello, the core calls the optional callback to give a chance to the swap the context depending on the input
+ * values. The callback is required to call `ptls_set_server_name` if an SNI extension needs to be sent to the client.
+ */
+PTLS_CALLBACK_TYPE(int, on_client_hello, ptls_t *tls, ptls_iovec_t server_name, const ptls_iovec_t *negotiated_protocols,
+ size_t num_negotiated_protocols, const uint16_t *signature_algorithms, size_t num_signature_algorithms);
+/**
+ * when generating Certificate, the core calls the callback to obtain the OCSP response for stapling.
+ */
+PTLS_CALLBACK_TYPE(int, staple_ocsp, ptls_t *tls, ptls_buffer_t *output, size_t cert_index);
+/**
+ * when gerenating CertificateVerify, the core calls the callback to sign the handshake context using the certificate.
+ */
+PTLS_CALLBACK_TYPE(int, sign_certificate, ptls_t *tls, uint16_t *selected_algorithm, ptls_buffer_t *output, ptls_iovec_t input,
+ const uint16_t *algorithms, size_t num_algorithms);
+/**
+ * after receiving Certificate, the core calls the callback to verify the certificate chain and to obtain a pointer to a
+ * callback that should be used for verifying CertificateVerify. If an error occurs between a successful return from this
+ * callback to the invocation of the verify_sign callback, verify_sign is called with both data and sign set to an empty buffer.
+ * The implementor of the callback should use that as the opportunity to free any temporary data allocated for the verify_sign
+ * callback.
+ */
+PTLS_CALLBACK_TYPE(int, verify_certificate, ptls_t *tls,
+ int (**verify_sign)(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t sign), void **verify_data,
+ ptls_iovec_t *certs, size_t num_certs);
+/**
+ * encrypt-and-signs (or verify-and-decrypts) a ticket (server-only)
+ */
+PTLS_CALLBACK_TYPE(int, encrypt_ticket, ptls_t *tls, int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src);
+/**
+ * saves a ticket (client-only)
+ */
+PTLS_CALLBACK_TYPE(int, save_ticket, ptls_t *tls, ptls_iovec_t input);
+/**
+ * secret logginng
+ */
+PTLS_CALLBACK_TYPE(void, log_secret, ptls_t *tls, const char *label, ptls_iovec_t secret);
+/**
+ * reference counting
+ */
+PTLS_CALLBACK_TYPE(void, update_open_count, ssize_t delta);
+
+/**
+ * the configuration
+ */
+struct st_ptls_context_t {
+ /**
+ * PRNG to be used
+ */
+ void (*random_bytes)(void *buf, size_t len);
+ /**
+ *
+ */
+ ptls_get_time_t *get_time;
+ /**
+ * list of supported key-exchange algorithms terminated by NULL
+ */
+ ptls_key_exchange_algorithm_t **key_exchanges;
+ /**
+ * list of supported cipher-suites terminated by NULL
+ */
+ ptls_cipher_suite_t **cipher_suites;
+ /**
+ * list of certificates
+ */
+ struct {
+ ptls_iovec_t *list;
+ size_t count;
+ } certificates;
+ /**
+ *
+ */
+ ptls_on_client_hello_t *on_client_hello;
+ /**
+ *
+ */
+ ptls_staple_ocsp_t *staple_ocsp;
+ /**
+ *
+ */
+ ptls_sign_certificate_t *sign_certificate;
+ /**
+ *
+ */
+ ptls_verify_certificate_t *verify_certificate;
+ /**
+ * lifetime of a session ticket (server-only)
+ */
+ uint32_t ticket_lifetime;
+ /**
+ * maximum permitted size of early data (server-only)
+ */
+ uint32_t max_early_data_size;
+ /**
+ * if set, psk handshakes use (ec)dhe
+ */
+ unsigned require_dhe_on_psk : 1;
+ /**
+ * if exporter master secrets should be recorded
+ */
+ unsigned use_exporter : 1;
+ /**
+ * if ChangeCipherSpec message should be sent during handshake
+ */
+ unsigned send_change_cipher_spec : 1;
+ /**
+ *
+ */
+ ptls_encrypt_ticket_t *encrypt_ticket;
+ /**
+ *
+ */
+ ptls_save_ticket_t *save_ticket;
+ /**
+ *
+ */
+ ptls_log_secret_t *log_secret;
+ /**
+ *
+ */
+ ptls_update_open_count_t *update_open_count;
+};
+
+typedef struct st_ptls_raw_extension_t {
+ uint16_t type;
+ ptls_iovec_t data;
+} ptls_raw_extension_t;
+
+/**
+ * optional arguments to client-driven handshake
+ */
+#ifdef _WINDOWS
+/* suppress warning C4201: nonstandard extension used: nameless struct/union */
+#pragma warning(push)
+#pragma warning(disable : 4201)
+#endif
+typedef struct st_ptls_handshake_properties_t {
+ union {
+ struct {
+ /**
+ * list of protocols offered through ALPN
+ */
+ struct {
+ const ptls_iovec_t *list;
+ size_t count;
+ } negotiated_protocols;
+ /**
+ * session ticket sent to the application via save_ticket callback
+ */
+ ptls_iovec_t session_ticket;
+ /**
+ * pointer to store the maximum size of early-data that can be sent immediately (if NULL, early data is not used)
+ */
+ size_t *max_early_data_size;
+ /**
+ *
+ */
+ unsigned early_data_accepted_by_peer : 1;
+ /**
+ * negotiate the key exchange method before sending key_share
+ */
+ unsigned negotiate_before_key_exchange : 1;
+ } client;
+ struct {
+ /**
+ * psk binder being selected (len is set to zero if none)
+ */
+ struct {
+ uint8_t base[PTLS_MAX_DIGEST_SIZE];
+ size_t len;
+ } selected_psk_binder;
+ /**
+ * parameters related to use of the Cookie extension
+ */
+ struct {
+ /**
+ * HMAC key to protect the integrity of the cookie. The key should be as long as the digest size of the first
+ * ciphersuite specified in ptls_context_t (i.e. the hash algorithm of the best ciphersuite that can be chosen).
+ */
+ const void *key;
+ /**
+ * additional data to be used for verifying the cookie
+ */
+ ptls_iovec_t additional_data;
+ } cookie;
+ /**
+ * if HRR should always be sent
+ */
+ unsigned enforce_retry : 1;
+ /**
+ * if retry should be stateless (cookie.key MUST be set when this option is used)
+ */
+ unsigned retry_uses_cookie : 1;
+ } server;
+ };
+ /**
+ * an optional list of additional extensions to send either in CH or EE, terminated by type == UINT16_MAX
+ */
+ ptls_raw_extension_t *additional_extensions;
+ /**
+ * an optional callback that returns a boolean value indicating if a particular extension should be collected
+ */
+ int (*collect_extension)(ptls_t *tls, struct st_ptls_handshake_properties_t *properties, uint16_t type);
+ /**
+ * an optional callback that reports the extensions being collected
+ */
+ int (*collected_extensions)(ptls_t *tls, struct st_ptls_handshake_properties_t *properties, ptls_raw_extension_t *extensions);
+} ptls_handshake_properties_t;
+#ifdef _WINDOWS
+#pragma warning(pop)
+#endif
+
+/**
+ * builds a new ptls_iovec_t instance using the supplied parameters
+ */
+static ptls_iovec_t ptls_iovec_init(const void *p, size_t len);
+/**
+ * initializes a buffer, setting the default destination to the small buffer provided as the argument.
+ */
+static void ptls_buffer_init(ptls_buffer_t *buf, void *smallbuf, size_t smallbuf_size);
+/**
+ * disposes a buffer, freeing resources allocated by the buffer itself (if any)
+ */
+static void ptls_buffer_dispose(ptls_buffer_t *buf);
+/**
+ * internal
+ */
+void ptls_buffer__release_memory(ptls_buffer_t *buf);
+/**
+ * reserves space for additional amount of memory
+ */
+int ptls_buffer_reserve(ptls_buffer_t *buf, size_t delta);
+/**
+ * internal
+ */
+int ptls_buffer__do_pushv(ptls_buffer_t *buf, const void *src, size_t len);
+/**
+ * internal
+ */
+int ptls_buffer__adjust_asn1_blocksize(ptls_buffer_t *buf, size_t body_size);
+/**
+ * pushes an unsigned bigint
+ */
+int ptls_buffer_push_asn1_ubigint(ptls_buffer_t *buf, const void *bignum, size_t size);
+
+#define ptls_buffer_pushv(buf, src, len) \
+ do { \
+ if ((ret = ptls_buffer__do_pushv((buf), (src), (len))) != 0) \
+ goto Exit; \
+ } while (0)
+
+#define ptls_buffer_push(buf, ...) \
+ do { \
+ if ((ret = ptls_buffer__do_pushv((buf), (uint8_t[]){__VA_ARGS__}, sizeof((uint8_t[]){__VA_ARGS__}))) != 0) \
+ goto Exit; \
+ } while (0)
+
+#define ptls_buffer_push16(buf, v) \
+ do { \
+ uint16_t _v = (v); \
+ ptls_buffer_push(buf, (uint8_t)(_v >> 8), (uint8_t)_v); \
+ } while (0)
+
+#define ptls_buffer_push32(buf, v) \
+ do { \
+ uint32_t _v = (v); \
+ ptls_buffer_push(buf, (uint8_t)(_v >> 24), (uint8_t)(_v >> 16), (uint8_t)(_v >> 8), (uint8_t)_v); \
+ } while (0)
+
+#define ptls_buffer_push64(buf, v) \
+ do { \
+ uint64_t _v = (v); \
+ ptls_buffer_push(buf, (uint8_t)(_v >> 56), (uint8_t)(_v >> 48), (uint8_t)(_v >> 40), (uint8_t)(_v >> 32), \
+ (uint8_t)(_v >> 24), (uint8_t)(_v >> 16), (uint8_t)(_v >> 8), (uint8_t)_v); \
+ } while (0)
+
+#define ptls_buffer_push_block(buf, _capacity, block) \
+ do { \
+ size_t capacity = (_capacity); \
+ ptls_buffer_pushv((buf), (uint8_t *)"\0\0\0\0\0\0\0", capacity); \
+ size_t body_start = (buf)->off; \
+ do { \
+ block \
+ } while (0); \
+ size_t body_size = (buf)->off - body_start; \
+ for (; capacity != 0; --capacity) \
+ (buf)->base[body_start - capacity] = (uint8_t)(body_size >> (8 * (capacity - 1))); \
+ } while (0)
+
+#define ptls_buffer_push_asn1_block(buf, block) \
+ do { \
+ ptls_buffer_push((buf), 0xff); /* dummy */ \
+ size_t body_start = (buf)->off; \
+ do { \
+ block \
+ } while (0); \
+ size_t body_size = (buf)->off - body_start; \
+ if (body_size < 128) { \
+ (buf)->base[body_start - 1] = (uint8_t)body_size; \
+ } else { \
+ if ((ret = ptls_buffer__adjust_asn1_blocksize((buf), body_size)) != 0) \
+ goto Exit; \
+ } \
+ } while (0)
+
+#define ptls_buffer_push_asn1_sequence(buf, block) \
+ do { \
+ ptls_buffer_push((buf), 0x30); \
+ ptls_buffer_push_asn1_block((buf), block); \
+ } while (0)
+
+int ptls_decode16(uint16_t *value, const uint8_t **src, const uint8_t *end);
+int ptls_decode32(uint32_t *value, const uint8_t **src, const uint8_t *end);
+int ptls_decode64(uint64_t *value, const uint8_t **src, const uint8_t *end);
+
+#define ptls_decode_open_block(src, end, capacity, block) \
+ do { \
+ size_t _capacity = (capacity); \
+ if (_capacity > (size_t)(end - (src))) { \
+ ret = PTLS_ALERT_DECODE_ERROR; \
+ goto Exit; \
+ } \
+ size_t _block_size = 0; \
+ do { \
+ _block_size = _block_size << 8 | *(src)++; \
+ } while (--_capacity != 0); \
+ if (_block_size > (size_t)(end - (src))) { \
+ ret = PTLS_ALERT_DECODE_ERROR; \
+ goto Exit; \
+ } \
+ do { \
+ const uint8_t *const end = (src) + _block_size; \
+ do { \
+ block \
+ } while (0); \
+ if ((src) != end) { \
+ ret = PTLS_ALERT_DECODE_ERROR; \
+ goto Exit; \
+ } \
+ } while (0); \
+ } while (0)
+
+#define ptls_decode_assert_block_close(src, end) \
+ do { \
+ if ((src) != end) { \
+ ret = PTLS_ALERT_DECODE_ERROR; \
+ goto Exit; \
+ } \
+ } while (0);
+
+#define ptls_decode_block(src, end, capacity, block) \
+ do { \
+ ptls_decode_open_block((src), end, capacity, block); \
+ ptls_decode_assert_block_close((src), end); \
+ } while (0)
+
+/**
+ * create a object to handle new TLS connection. Client-side of a TLS connection is created if server_name is non-NULL. Otherwise,
+ * a server-side connection is created.
+ */
+ptls_t *ptls_new(ptls_context_t *ctx, int is_server);
+/**
+ * releases all resources associated to the object
+ */
+void ptls_free(ptls_t *tls);
+/**
+ * returns address of the crypto callbacks that the connection is using
+ */
+ptls_context_t *ptls_get_context(ptls_t *tls);
+/**
+ * updates the context of a connection. Can be called from `on_client_hello` callback.
+ */
+void ptls_set_context(ptls_t *tls, ptls_context_t *ctx);
+/**
+ * returns the client-random
+ */
+ptls_iovec_t ptls_get_client_random(ptls_t *tls);
+/**
+ * returns the cipher-suite being used
+ */
+ptls_cipher_suite_t *ptls_get_cipher(ptls_t *tls);
+/**
+ * returns the server-name (NULL if SNI is not used or failed to negotiate)
+ */
+const char *ptls_get_server_name(ptls_t *tls);
+/**
+ * sets the server-name (for client the value sent in SNI). If server_name_len is zero, then strlen(server_name) is called to
+ * determine
+ * the length of the name.
+ */
+int ptls_set_server_name(ptls_t *tls, const char *server_name, size_t server_name_len);
+/**
+ * returns the negotiated protocol (or NULL)
+ */
+const char *ptls_get_negotiated_protocol(ptls_t *tls);
+/**
+ * sets the negotiated protocol. If protocol_len is zero, strlen(protocol) is called to determine the length of the protocol name.
+ */
+int ptls_set_negotiated_protocol(ptls_t *tls, const char *protocol, size_t protocol_len);
+/**
+ * returns if the handshake has been completed
+ */
+int ptls_handshake_is_complete(ptls_t *tls);
+/**
+ * returns if a PSK (or PSK-DHE) handshake was performed
+ */
+int ptls_is_psk_handshake(ptls_t *tls);
+/**
+ * returns a pointer to user data pointer (client is reponsible for freeing the associated data prior to calling ptls_free)
+ */
+void **ptls_get_data_ptr(ptls_t *tls);
+/**
+ * proceeds with the handshake, optionally taking some input from peer. The function returns zero in case the handshake completed
+ * successfully. PTLS_ERROR_IN_PROGRESS is returned in case the handshake is incomplete. Otherwise, an error value is returned. The
+ * contents of sendbuf should be sent to the client, regardless of whether if an error is returned. inlen is an argument used for
+ * both input and output. As an input, the arguments takes the size of the data available as input. Upon return the value is updated
+ * to the number of bytes consumed by the handshake. In case the returned value is PTLS_ERROR_IN_PROGRESS there is a guarantee that
+ * all the input are consumed (i.e. the value of inlen does not change).
+ */
+int ptls_handshake(ptls_t *tls, ptls_buffer_t *sendbuf, const void *input, size_t *inlen, ptls_handshake_properties_t *args);
+/**
+ * decrypts the first record within given buffer
+ */
+int ptls_receive(ptls_t *tls, ptls_buffer_t *plaintextbuf, const void *input, size_t *len);
+/**
+ * encrypts given buffer into multiple TLS records
+ */
+int ptls_send(ptls_t *tls, ptls_buffer_t *sendbuf, const void *input, size_t inlen);
+/**
+ * returns per-record overhead
+ */
+size_t ptls_get_record_overhead(ptls_t *tls);
+/**
+ * sends an alert
+ */
+int ptls_send_alert(ptls_t *tls, ptls_buffer_t *sendbuf, uint8_t level, uint8_t description);
+/**
+ *
+ */
+int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *label, ptls_iovec_t context_value, int is_early);
+/**
+ *
+ */
+ptls_hash_context_t *ptls_hmac_create(ptls_hash_algorithm_t *algo, const void *key, size_t key_size);
+/**
+ *
+ */
+int ptls_hkdf_extract(ptls_hash_algorithm_t *hash, void *output, ptls_iovec_t salt, ptls_iovec_t ikm);
+/**
+ *
+ */
+int ptls_hkdf_expand(ptls_hash_algorithm_t *hash, void *output, size_t outlen, ptls_iovec_t prk, ptls_iovec_t info);
+/**
+ *
+ */
+int ptls_hkdf_expand_label(ptls_hash_algorithm_t *algo, void *output, size_t outlen, ptls_iovec_t secret, const char *label,
+ ptls_iovec_t hash_value, const char *base_label);
+/**
+ * instantiates a symmetric cipher
+ */
+ptls_cipher_context_t *ptls_cipher_new(ptls_cipher_algorithm_t *algo, int is_enc, const void *key);
+/**
+ * destroys a symmetric cipher
+ */
+void ptls_cipher_free(ptls_cipher_context_t *ctx);
+/**
+ * initializes the IV; this function must be called prior to calling ptls_cipher_encrypt
+ */
+static void ptls_cipher_init(ptls_cipher_context_t *ctx, const void *iv);
+/**
+ * encrypts given text
+ */
+static void ptls_cipher_encrypt(ptls_cipher_context_t *ctx, void *output, const void *input, size_t len);
+/**
+ * instantiates an AEAD cipher given a secret, which is expanded using hkdf to a set of key and iv
+ * @param aead
+ * @param hash
+ * @param is_enc 1 if creating a context for encryption, 0 if creating a context for decryption
+ * @param secret the secret. The size must be the digest length of the hash algorithm
+ * @return pointer to an AEAD context if successful, otherwise NULL
+ */
+ptls_aead_context_t *ptls_aead_new(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t *hash, int is_enc, const void *secret,
+ const char *base_label);
+/**
+ * destroys an AEAD cipher context
+ */
+void ptls_aead_free(ptls_aead_context_t *ctx);
+/**
+ *
+ */
+size_t ptls_aead_encrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad,
+ size_t aadlen);
+/**
+ * initializes the internal state of the encryptor
+ */
+static void ptls_aead_encrypt_init(ptls_aead_context_t *ctx, uint64_t seq, const void *aad, size_t aadlen);
+/**
+ * encrypts the input and updates the GCM state
+ * @return number of bytes emitted to output
+ */
+static size_t ptls_aead_encrypt_update(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen);
+/**
+ * emits buffered data (if any) and the GCM tag
+ * @return number of bytes emitted to output
+ */
+static size_t ptls_aead_encrypt_final(ptls_aead_context_t *ctx, void *output);
+/**
+ * decrypts an AEAD record
+ * @return number of bytes emitted to output if successful, or SIZE_MAX if the input is invalid (e.g. broken MAC)
+ */
+static size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
+ const void *aad, size_t aadlen);
+/**
+ * internal
+ */
+void ptls_aead__build_iv(ptls_aead_context_t *ctx, uint8_t *iv, uint64_t seq);
+/**
+ * clears memory
+ */
+extern void (*volatile ptls_clear_memory)(void *p, size_t len);
+/**
+ *
+ */
+static ptls_iovec_t ptls_iovec_init(const void *p, size_t len);
+
+/* inline functions */
+inline ptls_iovec_t ptls_iovec_init(const void *p, size_t len)
+{
+ /* avoid the "return (ptls_iovec_t){(uint8_t *)p, len};" construct because it requires C99
+ * and triggers a warning "C4204: nonstandard extension used: non-constant aggregate initializer"
+ * in Visual Studio */
+ ptls_iovec_t r;
+ r.base = (uint8_t *)p;
+ r.len = len;
+ return r;
+}
+
+inline void ptls_buffer_init(ptls_buffer_t *buf, void *smallbuf, size_t smallbuf_size)
+{
+ assert(smallbuf != NULL);
+ buf->base = (uint8_t *)smallbuf;
+ buf->off = 0;
+ buf->capacity = smallbuf_size;
+ buf->is_allocated = 0;
+}
+
+inline void ptls_buffer_dispose(ptls_buffer_t *buf)
+{
+ ptls_buffer__release_memory(buf);
+ *buf = (ptls_buffer_t){NULL};
+}
+
+inline void ptls_cipher_init(ptls_cipher_context_t *ctx, const void *iv)
+{
+ ctx->do_init(ctx, iv);
+}
+
+inline void ptls_cipher_encrypt(ptls_cipher_context_t *ctx, void *output, const void *input, size_t len)
+{
+ ctx->do_transform(ctx, output, input, len);
+}
+
+inline void ptls_aead_encrypt_init(ptls_aead_context_t *ctx, uint64_t seq, const void *aad, size_t aadlen)
+{
+ uint8_t iv[PTLS_MAX_IV_SIZE];
+
+ ptls_aead__build_iv(ctx, iv, seq);
+ ctx->do_encrypt_init(ctx, iv, aad, aadlen);
+}
+
+inline size_t ptls_aead_encrypt_update(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen)
+{
+ return ctx->do_encrypt_update(ctx, output, input, inlen);
+}
+
+inline size_t ptls_aead_encrypt_final(ptls_aead_context_t *ctx, void *output)
+{
+ return ctx->do_encrypt_final(ctx, output);
+}
+
+inline size_t ptls_aead_decrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq,
+ const void *aad, size_t aadlen)
+{
+ uint8_t iv[PTLS_MAX_IV_SIZE];
+
+ ptls_aead__build_iv(ctx, iv, seq);
+ return ctx->do_decrypt(ctx, output, input, inlen, iv, aad, aadlen);
+}
+
+int ptls_load_certificates(ptls_context_t *ctx, char *cert_pem_file);
+
+extern ptls_get_time_t ptls_get_time;
+
+#define ptls_define_hash(name, ctx_type, init_func, update_func, final_func) \
+ \
+ struct name##_context_t { \
+ ptls_hash_context_t super; \
+ ctx_type ctx; \
+ }; \
+ \
+ static void name##_update(ptls_hash_context_t *_ctx, const void *src, size_t len) \
+ { \
+ struct name##_context_t *ctx = (struct name##_context_t *)_ctx; \
+ update_func(&ctx->ctx, src, len); \
+ } \
+ \
+ static void name##_final(ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode) \
+ { \
+ struct name##_context_t *ctx = (struct name##_context_t *)_ctx; \
+ if (mode == PTLS_HASH_FINAL_MODE_SNAPSHOT) { \
+ ctx_type copy = ctx->ctx; \
+ final_func(&copy, md); \
+ ptls_clear_memory(&copy, sizeof(copy)); \
+ return; \
+ } \
+ if (md != NULL) \
+ final_func(&ctx->ctx, md); \
+ switch (mode) { \
+ case PTLS_HASH_FINAL_MODE_FREE: \
+ ptls_clear_memory(&ctx->ctx, sizeof(ctx->ctx)); \
+ free(ctx); \
+ break; \
+ case PTLS_HASH_FINAL_MODE_RESET: \
+ init_func(&ctx->ctx); \
+ break; \
+ default: \
+ assert(!"FIXME"); \
+ break; \
+ } \
+ } \
+ \
+ static ptls_hash_context_t *name##_clone(ptls_hash_context_t *_src) \
+ { \
+ struct name##_context_t *dst, *src = (struct name##_context_t *)_src; \
+ if ((dst = malloc(sizeof(*dst))) == NULL) \
+ return NULL; \
+ *dst = *src; \
+ return &dst->super; \
+ } \
+ \
+ static ptls_hash_context_t *name##_create(void) \
+ { \
+ struct name##_context_t *ctx; \
+ if ((ctx = malloc(sizeof(*ctx))) == NULL) \
+ return NULL; \
+ ctx->super = (ptls_hash_context_t){name##_update, name##_final, name##_clone}; \
+ init_func(&ctx->ctx); \
+ return &ctx->super; \
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/include/picotls/asn1.h b/web/server/h2o/libh2o/deps/picotls/include/picotls/asn1.h
new file mode 100644
index 00000000..5314c58a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/include/picotls/asn1.h
@@ -0,0 +1,64 @@
+/*
+* Copyright (c) 2017 Christian Huitema <huitema@huitema.net>
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 PTLS_ASN1_H
+#define PTLS_ASN1_H
+
+// #include "picotls/minicrypto.h"
+
+/*
+* The ASN.1 functions take a "log context" parameter of type ptls_minicrypto_log_ctx_t.
+*
+* The log function in that code can be instantiated for example as:
+*
+* void log_printf(void * ctx, const char * format, ...)
+* {
+* va_list argptr;
+* va_start(argptr, format);
+* vfprintf(stderr, format, argptr);
+* }
+*
+* Using definitions from <stdio.h> and <stdarg.h>
+*/
+
+typedef struct st_ptls_minicrypto_log_ctx_t {
+ void *ctx;
+ void (*fn)(void *ctx, const char *format, ...);
+} ptls_minicrypto_log_ctx_t;
+
+size_t ptls_asn1_error_message(char const *error_label, size_t bytes_max, size_t byte_index, int level,
+ ptls_minicrypto_log_ctx_t *log_ctx);
+
+void ptls_asn1_dump_content(const uint8_t *bytes, size_t bytes_max, size_t byte_index, ptls_minicrypto_log_ctx_t *log_ctx);
+
+size_t ptls_asn1_read_type(const uint8_t *bytes, size_t bytes_max, int *structure_bit, int *type_class, uint32_t *type_number,
+ int *decode_error, int level, ptls_minicrypto_log_ctx_t *log_ctx);
+
+void ptls_asn1_print_type(int type_class, uint32_t type_number, int level, ptls_minicrypto_log_ctx_t *log_ctx);
+
+size_t ptls_asn1_read_length(const uint8_t *bytes, size_t bytes_max, size_t byte_index, uint32_t *length, int *indefinite_length,
+ size_t *last_byte, int *decode_error, int level, ptls_minicrypto_log_ctx_t *log_ctx);
+
+size_t ptls_asn1_get_expected_type_and_length(const uint8_t *bytes, size_t bytes_max, size_t byte_index, uint8_t expected_type,
+ uint32_t *length, int *indefinite_length, size_t *last_byte, int *decode_error,
+ ptls_minicrypto_log_ctx_t *log_ctx);
+
+size_t ptls_asn1_validation_recursive(const uint8_t *bytes, size_t bytes_max, int *decode_error, int level,
+ ptls_minicrypto_log_ctx_t *log_ctx);
+
+int ptls_asn1_validation(const uint8_t *bytes, size_t length, ptls_minicrypto_log_ctx_t *log_ctx);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/include/picotls/minicrypto.h b/web/server/h2o/libh2o/deps/picotls/include/picotls/minicrypto.h
new file mode 100644
index 00000000..ce7e58ec
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/include/picotls/minicrypto.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef picotls_minicrypto_h
+#define picotls_minicrypto_h
+
+#include "picotls.h"
+
+#define SECP256R1_PRIVATE_KEY_SIZE 32
+#define SECP256R1_PUBLIC_KEY_SIZE 65 /* including the header */
+#define SECP256R1_SHARED_SECRET_SIZE 32
+
+typedef struct st_ptls_minicrypto_secp256r1sha256_sign_certificate_t {
+ ptls_sign_certificate_t super;
+ uint8_t key[SECP256R1_PRIVATE_KEY_SIZE];
+} ptls_minicrypto_secp256r1sha256_sign_certificate_t;
+
+void ptls_minicrypto_random_bytes(void *buf, size_t len);
+
+int ptls_minicrypto_init_secp256r1sha256_sign_certificate(ptls_minicrypto_secp256r1sha256_sign_certificate_t *self,
+ ptls_iovec_t key);
+
+extern ptls_key_exchange_algorithm_t ptls_minicrypto_secp256r1, ptls_minicrypto_x25519;
+extern ptls_key_exchange_algorithm_t *ptls_minicrypto_key_exchanges[];
+extern ptls_cipher_algorithm_t ptls_minicrypto_aes128ctr, ptls_minicrypto_aes256ctr, ptls_minicrypto_chacha20;
+extern ptls_aead_algorithm_t ptls_minicrypto_aes128gcm, ptls_minicrypto_aes256gcm, ptls_minicrypto_chacha20poly1305;
+extern ptls_hash_algorithm_t ptls_minicrypto_sha256, ptls_minicrypto_sha384;
+extern ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256, ptls_minicrypto_aes256gcmsha384, ptls_minicrypto_chacha20poly1305sha256;
+extern ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[];
+
+typedef struct st_ptls_asn1_pkcs8_private_key_t {
+ ptls_iovec_t vec;
+ size_t algorithm_index;
+ uint32_t algorithm_length;
+ size_t parameters_index;
+ uint32_t parameters_length;
+ size_t key_data_index;
+ uint32_t key_data_length;
+} ptls_asn1_pkcs8_private_key_t;
+
+int ptls_minicrypto_load_private_key(ptls_context_t *ctx, char const *pem_fname);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/include/picotls/openssl.h b/web/server/h2o/libh2o/deps/picotls/include/picotls/openssl.h
new file mode 100644
index 00000000..459474ad
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/include/picotls/openssl.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef picotls_openssl_h
+#define picotls_openssl_h
+
+#include <openssl/opensslv.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/x509.h>
+#include "../picotls.h"
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define PTLS_OPENSSL_HAVE_CHACHA20_POLY1305
+#endif
+
+extern ptls_key_exchange_algorithm_t ptls_openssl_secp256r1;
+extern ptls_key_exchange_algorithm_t *ptls_openssl_key_exchanges[];
+extern ptls_cipher_algorithm_t ptls_openssl_aes128ctr;
+extern ptls_aead_algorithm_t ptls_openssl_aes128gcm;
+extern ptls_cipher_algorithm_t ptls_openssl_aes256ctr;
+extern ptls_aead_algorithm_t ptls_openssl_aes256gcm;
+extern ptls_hash_algorithm_t ptls_openssl_sha256;
+extern ptls_hash_algorithm_t ptls_openssl_sha384;
+extern ptls_cipher_suite_t ptls_openssl_aes128gcmsha256;
+extern ptls_cipher_suite_t ptls_openssl_aes256gcmsha384;
+extern ptls_cipher_suite_t *ptls_openssl_cipher_suites[];
+
+#if defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305)
+extern ptls_cipher_algorithm_t ptls_openssl_chacha20;
+extern ptls_aead_algorithm_t ptls_openssl_chacha20poly1305;
+extern ptls_cipher_suite_t ptls_openssl_chacha20poly1305sha256;
+#endif
+
+void ptls_openssl_random_bytes(void *buf, size_t len);
+
+struct st_ptls_openssl_signature_scheme_t {
+ uint16_t scheme_id;
+ const EVP_MD *scheme_md;
+};
+
+typedef struct st_ptls_openssl_sign_certificate_t {
+ ptls_sign_certificate_t super;
+ EVP_PKEY *key;
+ struct st_ptls_openssl_signature_scheme_t schemes[4]; /* terminated by .scheme_id == UINT16_MAX */
+} ptls_openssl_sign_certificate_t;
+
+int ptls_openssl_init_sign_certificate(ptls_openssl_sign_certificate_t *self, EVP_PKEY *key);
+void ptls_openssl_dispose_sign_certificate(ptls_openssl_sign_certificate_t *self);
+int ptls_openssl_load_certificates(ptls_context_t *ctx, X509 *cert, STACK_OF(X509) * chain);
+
+typedef struct st_ptls_openssl_verify_certificate_t {
+ ptls_verify_certificate_t super;
+ X509_STORE *cert_store;
+} ptls_openssl_verify_certificate_t;
+
+#define PTLS_OPENSSL_DEFAULT_CERTIFICATE_STORE ((X509_STORE *)1)
+
+int ptls_openssl_init_verify_certificate(ptls_openssl_verify_certificate_t *self, X509_STORE *store);
+void ptls_openssl_dispose_verify_certificate(ptls_openssl_verify_certificate_t *self);
+
+int ptls_openssl_encrypt_ticket(ptls_buffer_t *dst, ptls_iovec_t src,
+ int (*cb)(unsigned char *, unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int));
+int ptls_openssl_decrypt_ticket(ptls_buffer_t *dst, ptls_iovec_t src,
+ int (*cb)(unsigned char *, unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int));
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/include/picotls/pembase64.h b/web/server/h2o/libh2o/deps/picotls/include/picotls/pembase64.h
new file mode 100644
index 00000000..1b59910b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/include/picotls/pembase64.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (c) 2017 Christian Huitema <huitema@huitema.net>
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 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 PTLS_PEMBASE64_H
+#define PTLS_PEMBASE64_H
+
+/*
+* Base64 functions used in encoding and decoding of PEM files
+*/
+
+#define PTLS_BASE64_DECODE_DONE 0
+#define PTLS_BASE64_DECODE_IN_PROGRESS 1
+#define PTLS_BASE64_DECODE_FAILED -1
+
+typedef struct st_ptls_base64_decode_state_t {
+ int nbc;
+ int nbo;
+ int status;
+ uint32_t v;
+} ptls_base64_decode_state_t;
+
+int ptls_base64_encode(const uint8_t *data, size_t data_len, char *base64_text);
+
+size_t ptls_base64_howlong(size_t data_length);
+
+void ptls_base64_decode_init(ptls_base64_decode_state_t *state);
+int ptls_base64_decode(const char *base64_text, ptls_base64_decode_state_t *state, ptls_buffer_t *buf);
+
+int ptls_load_pem_objects(char const *pem_fname, const char *label, ptls_iovec_t *list, size_t list_max, size_t *nb_objects);
+
+#endif /* PTLS_PEMBASE64_H */
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/asn1.c b/web/server/h2o/libh2o/deps/picotls/lib/asn1.c
new file mode 100644
index 00000000..4422bed9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/asn1.c
@@ -0,0 +1,295 @@
+/*
+* Copyright (c) 2016 Christian Huitema <huitema@huitema.net>
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+* Basic ASN1 validation and optional print-out
+*/
+
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <sys/time.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+#include "picotls/asn1.h"
+
+static char const *asn1_type_classes[4] = {"Universal", "Application", "Context-specific", "Private"};
+
+static char const *asn1_universal_types[] = {
+ "End-of-Content", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL",
+ "OBJECT IDENTIFIER", "Object Descriptor", "EXTERNAL", "REAL", "ENUMERATED", "EMBEDDED PDV",
+ "UTF8String", "RELATIVE-OID", "Reserved (16)", "Reserved (17)", "SEQUENCE", "SET",
+ "NumericString", "PrintableString", "T61String", "VideotexString", "IA5String", "UTCTime",
+ "GeneralizedTime", "GraphicString", "VisibleString", "GeneralString", "UniversalString", "CHARACTER STRING",
+ "BMPString"};
+
+static size_t nb_asn1_universal_types = sizeof(asn1_universal_types) / sizeof(char const *);
+
+static void ptls_asn1_print_indent(int level, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ for (int indent = 0; indent <= level; indent++) {
+ log_ctx->fn(log_ctx->ctx, " ");
+ }
+}
+
+size_t ptls_asn1_error_message(char const *error_label, size_t bytes_max, size_t byte_index, int level,
+ ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ if (log_ctx != NULL) {
+ ptls_asn1_print_indent(level, log_ctx);
+ log_ctx->fn(log_ctx->ctx, "Error: %s (near position: %d (0x%x) out of %d)", error_label, (int)byte_index,
+ (uint32_t)byte_index, (int)bytes_max);
+ }
+ return byte_index;
+}
+
+void ptls_asn1_dump_content(const uint8_t *bytes, size_t bytes_max, size_t byte_index, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ if (log_ctx != NULL && bytes_max > byte_index) {
+ size_t nb_bytes = bytes_max - byte_index;
+
+ log_ctx->fn(log_ctx->ctx, " ");
+
+ for (size_t i = 0; i < 16 && i < nb_bytes; i++) {
+ log_ctx->fn(log_ctx->ctx, "%02x", bytes[byte_index + i]);
+ }
+
+ if (nb_bytes > 16) {
+ log_ctx->fn(log_ctx->ctx, "...");
+ }
+ }
+}
+
+size_t ptls_asn1_read_type(const uint8_t *bytes, size_t bytes_max, int *structure_bit, int *type_class, uint32_t *type_number,
+ int *decode_error, int level, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ /* Get the type byte */
+ size_t byte_index = 1;
+ uint8_t first_byte = bytes[0];
+ *structure_bit = (first_byte >> 5) & 1;
+ *type_class = (first_byte >> 6) & 3;
+ *type_number = first_byte & 31;
+
+ if (*type_number == 31) {
+ uint32_t long_type = 0;
+ const uint32_t type_number_limit = 0x07FFFFFFF;
+ int next_byte;
+ int end_found = 0;
+
+ while (byte_index < bytes_max && long_type <= type_number_limit) {
+ next_byte = bytes[byte_index++];
+ long_type <<= 7;
+ long_type |= next_byte & 127;
+ if ((next_byte & 128) == 0) {
+ end_found = 1;
+ break;
+ }
+ }
+
+ if (end_found) {
+ *type_number = long_type;
+ } else {
+ /* This is an error */
+ byte_index = ptls_asn1_error_message("Incorrect type coding", bytes_max, byte_index, level, log_ctx);
+ *decode_error = PTLS_ERROR_BER_MALFORMED_TYPE;
+ }
+ }
+
+ return byte_index;
+}
+
+void ptls_asn1_print_type(int type_class, uint32_t type_number, int level, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ /* Print the type */
+ ptls_asn1_print_indent(level, log_ctx);
+ if (type_class == 0 && type_number < nb_asn1_universal_types) {
+ log_ctx->fn(log_ctx->ctx, "%s", asn1_universal_types[type_number]);
+ } else if (type_class == 2) {
+ log_ctx->fn(log_ctx->ctx, "[%d]", type_number);
+ } else {
+ log_ctx->fn(log_ctx->ctx, "%s[%d]", asn1_type_classes[type_class], type_number);
+ }
+}
+
+size_t ptls_asn1_read_length(const uint8_t *bytes, size_t bytes_max, size_t byte_index, uint32_t *length, int *indefinite_length,
+ size_t *last_byte, int *decode_error, int level, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ int length_of_length = 0;
+
+ *indefinite_length = 0;
+ *length = 0;
+ *last_byte = bytes_max;
+
+ if (byte_index < bytes_max) {
+ *length = bytes[byte_index++];
+ if ((*length & 128) != 0) {
+ length_of_length = *length & 127;
+ *length = 0;
+
+ if (byte_index + length_of_length >= bytes_max) {
+ /* This is an error */
+ byte_index = ptls_asn1_error_message("Incorrect length coding", bytes_max, byte_index, level, log_ctx);
+ *decode_error = PTLS_ERROR_BER_MALFORMED_LENGTH;
+ } else {
+ for (int i = 0; i < length_of_length && byte_index < bytes_max; i++) {
+ *length <<= 8;
+ *length |= bytes[byte_index++];
+ }
+
+ if (length_of_length == 0) {
+ *last_byte = bytes_max;
+ *indefinite_length = 1;
+ } else {
+ *last_byte = byte_index + *length;
+ }
+ }
+ } else {
+ *last_byte = byte_index + *length;
+ }
+
+ if (*decode_error == 0) {
+ /* TODO: verify that the length makes sense */
+ if (*last_byte > bytes_max) {
+ byte_index = ptls_asn1_error_message("Length larger than message", bytes_max, byte_index, level, log_ctx);
+ *decode_error = PTLS_ERROR_BER_EXCESSIVE_LENGTH;
+ }
+ }
+ }
+
+ return byte_index;
+}
+
+size_t ptls_asn1_get_expected_type_and_length(const uint8_t *bytes, size_t bytes_max, size_t byte_index, uint8_t expected_type,
+ uint32_t *length, int *indefinite_length, size_t *last_byte, int *decode_error,
+ ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ int is_indefinite = 0;
+
+ /* Check that the expected type is present */
+ if (bytes[byte_index] != expected_type) {
+ byte_index = ptls_asn1_error_message("Unexpected type", bytes_max, byte_index, 0, log_ctx);
+ *decode_error = PTLS_ERROR_INCORRECT_ASN1_SYNTAX;
+ } else {
+ /* get length of element */
+ byte_index++;
+ byte_index =
+ ptls_asn1_read_length(bytes, bytes_max, byte_index, length, &is_indefinite, last_byte, decode_error, 0, log_ctx);
+
+ if (indefinite_length != NULL) {
+ *indefinite_length = is_indefinite;
+ } else if (is_indefinite) {
+ byte_index = ptls_asn1_error_message("Incorrect length for DER", bytes_max, byte_index, 0, log_ctx);
+ *decode_error = PTLS_ERROR_DER_INDEFINITE_LENGTH;
+ }
+ }
+
+ return byte_index;
+}
+
+size_t ptls_asn1_validation_recursive(const uint8_t *bytes, size_t bytes_max, int *decode_error, int level,
+ ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ /* Get the type byte */
+ int structure_bit = 0;
+ int type_class = 0;
+ uint32_t type_number = 0;
+ uint32_t length = 0;
+ int indefinite_length = 0;
+ size_t last_byte = 0;
+ /* Decode the type */
+ size_t byte_index =
+ ptls_asn1_read_type(bytes, bytes_max, &structure_bit, &type_class, &type_number, decode_error, level, log_ctx);
+
+ if (*decode_error == 0 && log_ctx != NULL) {
+ ptls_asn1_print_type(type_class, type_number, level, log_ctx);
+ }
+
+ /* Get the length */
+ byte_index =
+ ptls_asn1_read_length(bytes, bytes_max, byte_index, &length, &indefinite_length, &last_byte, decode_error, level, log_ctx);
+
+ if (last_byte <= bytes_max) {
+ if (structure_bit) {
+ /* If structured, recurse on a loop */
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, " {\n");
+ }
+
+ while (byte_index < last_byte) {
+ if (indefinite_length != 0 && bytes[byte_index] == 0) {
+ if (byte_index + 2 > bytes_max || bytes[byte_index + 1] != 0) {
+ byte_index =
+ ptls_asn1_error_message("EOC: unexpected end of content", bytes_max, byte_index, level + 1, log_ctx);
+
+ *decode_error = PTLS_ERROR_BER_UNEXPECTED_EOC;
+ } else {
+ if (log_ctx != NULL) {
+ ptls_asn1_print_indent(level, log_ctx);
+ log_ctx->fn(log_ctx->ctx, "EOC\n");
+ }
+ byte_index += 2;
+ break;
+ }
+ } else {
+ byte_index += ptls_asn1_validation_recursive(bytes + byte_index, last_byte - byte_index, decode_error,
+ level + 1, log_ctx);
+
+ if (*decode_error) {
+ byte_index = bytes_max;
+ break;
+ }
+ }
+
+ if (log_ctx != NULL) {
+ if (byte_index < last_byte) {
+ log_ctx->fn(log_ctx->ctx, ",");
+ }
+ log_ctx->fn(log_ctx->ctx, "\n");
+ }
+ }
+
+ if (log_ctx != NULL) {
+ ptls_asn1_print_indent(level, log_ctx);
+ log_ctx->fn(log_ctx->ctx, "}");
+ }
+ } else {
+ ptls_asn1_dump_content(bytes, last_byte, byte_index, log_ctx);
+ byte_index = last_byte;
+ }
+ }
+
+ return byte_index;
+}
+
+int ptls_asn1_validation(const uint8_t *bytes, size_t length, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ int decode_error = 0;
+ size_t decoded = ptls_asn1_validation_recursive(bytes, length, &decode_error, 0, log_ctx);
+
+ if (decode_error == 0 && decoded < length) {
+ decode_error = PTLS_ERROR_BER_ELEMENT_TOO_SHORT;
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, "Type too short, %d bytes only out of %d\n", (int)decoded, (int)length);
+ }
+ }
+
+ return decode_error;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/cifra.c b/web/server/h2o/libh2o/deps/picotls/lib/cifra.c
new file mode 100644
index 00000000..af33c33f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/cifra.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <unistd.h>
+#endif
+#include "aes.h"
+#include "bitops.h"
+#include "drbg.h"
+#include "curve25519.h"
+#include "../deps/cifra/src/ext/handy.h"
+#include "modes.h"
+#include "poly1305.h"
+#include "salsa20.h"
+#include "sha2.h"
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+
+#ifdef _WINDOWS
+#include <wincrypt.h>
+static void read_entropy(uint8_t *entropy, size_t size)
+{
+ HCRYPTPROV hCryptProv = 0;
+ BOOL ret = FALSE;
+
+ if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
+ ret = CryptGenRandom(hCryptProv, (DWORD)size, entropy);
+ (void)CryptReleaseContext(hCryptProv, 0);
+ }
+
+ if (ret == FALSE) {
+ abort();
+ }
+}
+#else
+static void read_entropy(uint8_t *entropy, size_t size)
+{
+ int fd;
+
+ if ((fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) == -1) {
+ if ((fd = open("/dev/random", O_RDONLY | O_CLOEXEC)) == -1) {
+ perror("ptls_minicrypto_random_bytes: could not open neither /dev/random or /dev/urandom");
+ abort();
+ }
+ }
+
+ while (size != 0) {
+ ssize_t rret;
+ while ((rret = read(fd, entropy, size)) == -1 && errno == EINTR)
+ ;
+ if (rret < 0) {
+ perror("ptls_minicrypto_random_bytes");
+ abort();
+ }
+ entropy += rret;
+ size -= rret;
+ }
+
+ close(fd);
+}
+#endif
+
+void ptls_minicrypto_random_bytes(void *buf, size_t len)
+{
+#ifdef _WINDOWS
+ static __declspec(thread) cf_hash_drbg_sha256 ctx;
+#else
+ static __thread cf_hash_drbg_sha256 ctx;
+#endif
+
+ if (cf_hash_drbg_sha256_needs_reseed(&ctx)) {
+ uint8_t entropy[256];
+ read_entropy(entropy, sizeof(entropy));
+ cf_hash_drbg_sha256_init(&ctx, entropy, sizeof(entropy) / 2, entropy + sizeof(entropy) / 2, sizeof(entropy) / 2, "ptls", 4);
+ }
+ cf_hash_drbg_sha256_gen(&ctx, buf, len);
+}
+
+#define X25519_KEY_SIZE 32
+
+struct st_x25519_key_exchange_t {
+ ptls_key_exchange_context_t super;
+ uint8_t priv[X25519_KEY_SIZE];
+ uint8_t pub[X25519_KEY_SIZE];
+};
+
+static void x25519_create_keypair(uint8_t *priv, uint8_t *pub)
+{
+ ptls_minicrypto_random_bytes(priv, X25519_KEY_SIZE);
+ cf_curve25519_mul_base(pub, priv);
+}
+
+static int x25519_derive_secret(ptls_iovec_t *secret, const uint8_t *clientpriv, const uint8_t *clientpub,
+ const uint8_t *serverpriv, const uint8_t *serverpub)
+{
+ if ((secret->base = malloc(X25519_KEY_SIZE)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+
+ cf_curve25519_mul(secret->base, clientpriv != NULL ? clientpriv : serverpriv, clientpriv != NULL ? serverpub : clientpub);
+ secret->len = X25519_KEY_SIZE;
+ return 0;
+}
+
+static int x25519_on_exchange(ptls_key_exchange_context_t **_ctx, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ struct st_x25519_key_exchange_t *ctx = (struct st_x25519_key_exchange_t *)*_ctx;
+ int ret;
+
+ *_ctx = NULL;
+
+ if (secret == NULL) {
+ ret = 0;
+ goto Exit;
+ }
+
+ if (peerkey.len != X25519_KEY_SIZE) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ ret = x25519_derive_secret(secret, ctx->priv, ctx->pub, NULL, peerkey.base);
+
+Exit:
+ ptls_clear_memory(ctx->priv, sizeof(ctx->priv));
+ free(ctx);
+ return ret;
+}
+
+static int x25519_create_key_exchange(ptls_key_exchange_context_t **_ctx, ptls_iovec_t *pubkey)
+{
+ struct st_x25519_key_exchange_t *ctx;
+
+ if ((ctx = (struct st_x25519_key_exchange_t *)malloc(sizeof(*ctx))) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ ctx->super = (ptls_key_exchange_context_t){x25519_on_exchange};
+ x25519_create_keypair(ctx->priv, ctx->pub);
+
+ *_ctx = &ctx->super;
+ *pubkey = ptls_iovec_init(ctx->pub, sizeof(ctx->pub));
+ return 0;
+}
+
+static int x25519_key_exchange(ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ uint8_t priv[X25519_KEY_SIZE], *pub = NULL;
+ int ret;
+
+ if (peerkey.len != X25519_KEY_SIZE) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ if ((pub = malloc(X25519_KEY_SIZE)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ x25519_create_keypair(priv, pub);
+ if ((ret = x25519_derive_secret(secret, NULL, peerkey.base, priv, pub)) != 0)
+ goto Exit;
+
+ *pubkey = ptls_iovec_init(pub, X25519_KEY_SIZE);
+ ret = 0;
+
+Exit:
+ ptls_clear_memory(priv, sizeof(priv));
+ if (pub != NULL && ret != 0)
+ ptls_clear_memory(pub, X25519_KEY_SIZE);
+ return ret;
+}
+
+struct aesctr_context_t {
+ ptls_cipher_context_t super;
+ cf_aes_context aes;
+ cf_ctr ctr;
+};
+
+static void aesctr_dispose(ptls_cipher_context_t *_ctx)
+{
+ struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+ ptls_clear_memory(ctx, sizeof(*ctx));
+}
+
+static void aesctr_init(ptls_cipher_context_t *_ctx, const void *iv)
+{
+ struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+ cf_ctr_init(&ctx->ctr, &cf_aes, &ctx->aes, iv);
+}
+
+static void aesctr_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
+{
+ struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+ cf_ctr_cipher(&ctx->ctr, input, output, len);
+}
+
+static int aesctr_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key, size_t key_size)
+{
+ struct aesctr_context_t *ctx = (struct aesctr_context_t *)_ctx;
+ ctx->super.do_dispose = aesctr_dispose;
+ ctx->super.do_init = aesctr_init;
+ ctx->super.do_transform = aesctr_transform;
+ cf_aes_init(&ctx->aes, key, key_size);
+ return 0;
+}
+
+static int aes128ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+ return aesctr_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
+}
+
+static int aes256ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+ return aesctr_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
+}
+
+struct aesgcm_context_t {
+ ptls_aead_context_t super;
+ cf_aes_context aes;
+ cf_gcm_ctx gcm;
+};
+
+static void aesgcm_dispose_crypto(ptls_aead_context_t *_ctx)
+{
+ struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+ /* clear all memory except super */
+ ptls_clear_memory((uint8_t *)ctx + sizeof(ctx->super), sizeof(*ctx) - sizeof(ctx->super));
+}
+
+static void aesgcm_encrypt_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
+{
+ struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+ cf_gcm_encrypt_init(&cf_aes, &ctx->aes, &ctx->gcm, aad, aadlen, iv, PTLS_AESGCM_IV_SIZE);
+}
+
+static size_t aesgcm_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
+{
+ struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+ cf_gcm_encrypt_update(&ctx->gcm, input, inlen, output);
+ return inlen;
+}
+
+static size_t aesgcm_encrypt_final(ptls_aead_context_t *_ctx, void *output)
+{
+ struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+ cf_gcm_encrypt_final(&ctx->gcm, output, PTLS_AESGCM_TAG_SIZE);
+ return PTLS_AESGCM_TAG_SIZE;
+}
+
+static size_t aesgcm_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, const void *iv,
+ const void *aad, size_t aadlen)
+{
+ struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+ if (inlen < PTLS_AESGCM_TAG_SIZE)
+ return SIZE_MAX;
+ size_t tag_offset = inlen - PTLS_AESGCM_TAG_SIZE;
+
+ if (cf_gcm_decrypt(&cf_aes, &ctx->aes, input, tag_offset, aad, aadlen, iv, PTLS_AESGCM_IV_SIZE, (uint8_t *)input + tag_offset,
+ PTLS_AESGCM_TAG_SIZE, output) != 0)
+ return SIZE_MAX;
+
+ return tag_offset;
+}
+
+static int aead_aesgcm_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, size_t key_size)
+{
+ struct aesgcm_context_t *ctx = (struct aesgcm_context_t *)_ctx;
+
+ ctx->super.dispose_crypto = aesgcm_dispose_crypto;
+ if (is_enc) {
+ ctx->super.do_encrypt_init = aesgcm_encrypt_init;
+ ctx->super.do_encrypt_update = aesgcm_encrypt_update;
+ ctx->super.do_encrypt_final = aesgcm_encrypt_final;
+ ctx->super.do_decrypt = NULL;
+ } else {
+ ctx->super.do_encrypt_init = NULL;
+ ctx->super.do_encrypt_update = NULL;
+ ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_decrypt = aesgcm_decrypt;
+ }
+
+ cf_aes_init(&ctx->aes, key, key_size);
+ return 0;
+}
+
+static int aead_aes128gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+ return aead_aesgcm_setup_crypto(ctx, is_enc, key, PTLS_AES128_KEY_SIZE);
+}
+
+static int aead_aes256gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+ return aead_aesgcm_setup_crypto(ctx, is_enc, key, PTLS_AES256_KEY_SIZE);
+}
+
+struct chacha20_context_t {
+ ptls_cipher_context_t super;
+ cf_chacha20_ctx chacha;
+ uint8_t key[PTLS_CHACHA20_KEY_SIZE];
+};
+
+static void chacha20_dispose(ptls_cipher_context_t *_ctx)
+{
+ struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+ ptls_clear_memory(ctx, sizeof(*ctx));
+}
+
+static void chacha20_init(ptls_cipher_context_t *_ctx, const void *iv)
+{
+ struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+ ctx->chacha.nblock = 0;
+ ctx->chacha.ncounter = 0;
+ memcpy(ctx->chacha.nonce, iv, sizeof ctx->chacha.nonce);
+}
+
+static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
+{
+ struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+ cf_chacha20_cipher(&ctx->chacha, input, output, len);
+}
+
+static int chacha20_setup_crypto(ptls_cipher_context_t *_ctx, int is_enc, const void *key)
+{
+ struct chacha20_context_t *ctx = (struct chacha20_context_t *)_ctx;
+ ctx->super.do_dispose = chacha20_dispose;
+ ctx->super.do_init = chacha20_init;
+ ctx->super.do_transform = chacha20_transform;
+ cf_chacha20_init(&ctx->chacha, key, PTLS_CHACHA20_KEY_SIZE, (const uint8_t *)"01234567" /* not used */);
+ return 0;
+}
+
+struct chacha20poly1305_context_t {
+ ptls_aead_context_t super;
+ uint8_t key[PTLS_CHACHA20_KEY_SIZE];
+ cf_chacha20_ctx chacha;
+ cf_poly1305 poly;
+ size_t aadlen;
+ size_t textlen;
+};
+
+static void chacha20poly1305_dispose_crypto(ptls_aead_context_t *_ctx)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ /* clear all memory except super */
+ ptls_clear_memory(&ctx->key, sizeof(*ctx) - offsetof(struct chacha20poly1305_context_t, key));
+}
+
+static const uint8_t zeros64[64] = {0};
+
+static void chacha20poly1305_encrypt_pad(cf_poly1305 *poly, size_t n)
+{
+ if (n % 16 != 0)
+ cf_poly1305_update(poly, zeros64, 16 - (n % 16));
+}
+
+static void chacha20poly1305_finalize(struct chacha20poly1305_context_t *ctx, uint8_t *tag)
+{
+ uint8_t lenbuf[16];
+
+ chacha20poly1305_encrypt_pad(&ctx->poly, ctx->textlen);
+
+ write64_le(ctx->aadlen, lenbuf);
+ write64_le(ctx->textlen, lenbuf + 8);
+ cf_poly1305_update(&ctx->poly, lenbuf, sizeof(lenbuf));
+
+ cf_poly1305_finish(&ctx->poly, tag);
+}
+
+static void chacha20poly1305_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+ uint8_t tmpbuf[64];
+
+ /* init chacha */
+ memset(tmpbuf, 0, 16 - PTLS_CHACHA20POLY1305_IV_SIZE);
+ memcpy(tmpbuf + 16 - PTLS_CHACHA20POLY1305_IV_SIZE, iv, PTLS_CHACHA20POLY1305_IV_SIZE);
+ cf_chacha20_init_custom(&ctx->chacha, ctx->key, sizeof(ctx->key), tmpbuf, 4);
+
+ /* init poly1305 (by using first 16 bytes of the key stream of the first block) */
+ cf_chacha20_cipher(&ctx->chacha, zeros64, tmpbuf, 64);
+ cf_poly1305_init(&ctx->poly, tmpbuf, tmpbuf + 16);
+
+ ptls_clear_memory(tmpbuf, sizeof(tmpbuf));
+
+ /* aad */
+ if (aadlen != 0) {
+ cf_poly1305_update(&ctx->poly, aad, aadlen);
+ chacha20poly1305_encrypt_pad(&ctx->poly, aadlen);
+ }
+
+ ctx->aadlen = aadlen;
+ ctx->textlen = 0;
+}
+
+static size_t chacha20poly1305_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ cf_chacha20_cipher(&ctx->chacha, input, output, inlen);
+ cf_poly1305_update(&ctx->poly, output, inlen);
+ ctx->textlen += inlen;
+
+ return inlen;
+}
+
+static size_t chacha20poly1305_encrypt_final(ptls_aead_context_t *_ctx, void *output)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ chacha20poly1305_finalize(ctx, output);
+
+ ptls_clear_memory(&ctx->chacha, sizeof(ctx->chacha));
+ return PTLS_CHACHA20POLY1305_TAG_SIZE;
+}
+
+static size_t chacha20poly1305_decrypt(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, const void *iv,
+ const void *aad, size_t aadlen)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+ uint8_t tag[PTLS_CHACHA20POLY1305_TAG_SIZE];
+ size_t ret;
+
+ if (inlen < sizeof(tag))
+ return SIZE_MAX;
+
+ chacha20poly1305_init(&ctx->super, iv, aad, aadlen);
+
+ cf_poly1305_update(&ctx->poly, input, inlen - sizeof(tag));
+ ctx->textlen = inlen - sizeof(tag);
+
+ chacha20poly1305_finalize(ctx, tag);
+ if (mem_eq(tag, (const uint8_t *)input + inlen - sizeof(tag), sizeof(tag))) {
+ cf_chacha20_cipher(&ctx->chacha, input, output, inlen - sizeof(tag));
+ ret = inlen - sizeof(tag);
+ } else {
+ ret = SIZE_MAX;
+ }
+
+ ptls_clear_memory(tag, sizeof(tag));
+ ptls_clear_memory(&ctx->poly, sizeof(ctx->poly));
+
+ return ret;
+}
+
+static int aead_chacha20poly1305_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key)
+{
+ struct chacha20poly1305_context_t *ctx = (struct chacha20poly1305_context_t *)_ctx;
+
+ ctx->super.dispose_crypto = chacha20poly1305_dispose_crypto;
+ if (is_enc) {
+ ctx->super.do_encrypt_init = chacha20poly1305_init;
+ ctx->super.do_encrypt_update = chacha20poly1305_encrypt_update;
+ ctx->super.do_encrypt_final = chacha20poly1305_encrypt_final;
+ ctx->super.do_decrypt = NULL;
+ } else {
+ ctx->super.do_encrypt_init = NULL;
+ ctx->super.do_encrypt_update = NULL;
+ ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_decrypt = chacha20poly1305_decrypt;
+ }
+
+ memcpy(ctx->key, key, sizeof(ctx->key));
+ return 0;
+}
+
+ptls_define_hash(sha256, cf_sha256_context, cf_sha256_init, cf_sha256_update, cf_sha256_digest_final);
+ptls_define_hash(sha384, cf_sha512_context, cf_sha384_init, cf_sha384_update, cf_sha384_digest_final);
+
+ptls_key_exchange_algorithm_t ptls_minicrypto_x25519 = {PTLS_GROUP_X25519, x25519_create_key_exchange, x25519_key_exchange};
+ptls_cipher_algorithm_t ptls_minicrypto_aes128ctr = {"AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_IV_SIZE,
+ sizeof(struct aesctr_context_t), aes128ctr_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_aes128gcm = {
+ "AES128-GCM", &ptls_minicrypto_aes128ctr, PTLS_AES128_KEY_SIZE, PTLS_AESGCM_IV_SIZE,
+ PTLS_AESGCM_TAG_SIZE, sizeof(struct aesgcm_context_t), aead_aes128gcm_setup_crypto};
+ptls_cipher_algorithm_t ptls_minicrypto_aes256ctr = {"AES256-CTR", PTLS_AES256_KEY_SIZE, PTLS_AES_IV_SIZE,
+ sizeof(struct aesctr_context_t), aes256ctr_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_aes256gcm = {
+ "AES256-GCM", &ptls_minicrypto_aes256ctr, PTLS_AES256_KEY_SIZE, PTLS_AESGCM_IV_SIZE,
+ PTLS_AESGCM_TAG_SIZE, sizeof(struct aesgcm_context_t), aead_aes256gcm_setup_crypto};
+ptls_hash_algorithm_t ptls_minicrypto_sha256 = {PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, sha256_create,
+ PTLS_ZERO_DIGEST_SHA256};
+ptls_hash_algorithm_t ptls_minicrypto_sha384 = {PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create,
+ PTLS_ZERO_DIGEST_SHA384};
+ptls_cipher_algorithm_t ptls_minicrypto_chacha20 = {"CHACHA20", PTLS_CHACHA20_KEY_SIZE, PTLS_CHACHA20_IV_SIZE,
+ sizeof(struct chacha20_context_t), chacha20_setup_crypto};
+ptls_aead_algorithm_t ptls_minicrypto_chacha20poly1305 = {"CHACHA20-POLY1305",
+ &ptls_minicrypto_chacha20,
+ PTLS_CHACHA20_KEY_SIZE,
+ PTLS_CHACHA20POLY1305_IV_SIZE,
+ PTLS_CHACHA20POLY1305_TAG_SIZE,
+ sizeof(struct chacha20poly1305_context_t),
+ aead_chacha20poly1305_setup_crypto};
+ptls_cipher_suite_t ptls_minicrypto_aes128gcmsha256 = {PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, &ptls_minicrypto_aes128gcm,
+ &ptls_minicrypto_sha256};
+ptls_cipher_suite_t ptls_minicrypto_aes256gcmsha384 = {PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, &ptls_minicrypto_aes256gcm,
+ &ptls_minicrypto_sha384};
+ptls_cipher_suite_t ptls_minicrypto_chacha20poly1305sha256 = {PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256,
+ &ptls_minicrypto_chacha20poly1305, &ptls_minicrypto_sha256};
+ptls_cipher_suite_t *ptls_minicrypto_cipher_suites[] = {&ptls_minicrypto_aes256gcmsha384, &ptls_minicrypto_aes128gcmsha256,
+ &ptls_minicrypto_chacha20poly1305sha256, NULL};
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/minicrypto-pem.c b/web/server/h2o/libh2o/deps/picotls/lib/minicrypto-pem.c
new file mode 100644
index 00000000..2b82a91e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/minicrypto-pem.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2017,2018 Christian Huitema
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <unistd.h>
+#endif
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+#include "picotls/asn1.h"
+#include "picotls/pembase64.h"
+
+
+/*
+ * This function could be declared as static, but we want to access it
+ * in the unit tests.
+ */
+size_t ptls_minicrypto_asn1_decode_private_key(ptls_asn1_pkcs8_private_key_t *pkey, int *decode_error,
+ ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ uint8_t *bytes = pkey->vec.base;
+ size_t bytes_max = pkey->vec.len;
+
+ /* read the ASN1 messages */
+ size_t byte_index = 0;
+ uint32_t seq0_length = 0;
+ size_t last_byte0;
+ uint32_t seq1_length = 0;
+ size_t last_byte1 = 0;
+ uint32_t oid_length;
+ size_t last_oid_byte;
+ uint32_t key_data_length;
+ size_t key_data_last;
+
+ /* start with sequence */
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, bytes_max, byte_index, 0x30, &seq0_length, NULL, &last_byte0,
+ decode_error, log_ctx);
+
+ if (*decode_error == 0 && bytes_max != last_byte0) {
+ byte_index = ptls_asn1_error_message("Length larger than message", bytes_max, byte_index, 0, log_ctx);
+ *decode_error = PTLS_ERROR_BER_EXCESSIVE_LENGTH;
+ }
+
+ if (*decode_error == 0) {
+ /* get first component: version, INTEGER, expect value 0 */
+ if (byte_index + 3 > bytes_max) {
+ byte_index = ptls_asn1_error_message("Cannot find key version", bytes_max, byte_index, 0, log_ctx);
+ *decode_error = PTLS_ERROR_INCORRECT_PEM_KEY_VERSION;
+ } else if (bytes[byte_index] != 0x02 || bytes[byte_index + 1] != 0x01 || bytes[byte_index + 2] != 0x00) {
+ *decode_error = PTLS_ERROR_INCORRECT_PEM_KEY_VERSION;
+ byte_index = ptls_asn1_error_message("Incorrect PEM Version", bytes_max, byte_index, 0, log_ctx);
+ } else {
+ byte_index += 3;
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, " Version = 1,\n");
+ }
+ }
+ }
+
+ if (*decode_error == 0) {
+ /* open embedded sequence */
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, bytes_max, byte_index, 0x30, &seq1_length, NULL, &last_byte1,
+ decode_error, log_ctx);
+ }
+
+ if (*decode_error == 0) {
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, " Algorithm Identifier:\n");
+ }
+ /* get length of OID */
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, last_byte1, byte_index, 0x06, &oid_length, NULL, &last_oid_byte,
+ decode_error, log_ctx);
+
+ if (*decode_error == 0) {
+ if (log_ctx != NULL) {
+ /* print the OID value */
+ log_ctx->fn(log_ctx->ctx, " Algorithm:");
+ ptls_asn1_dump_content(bytes + byte_index, oid_length, 0, log_ctx);
+ log_ctx->fn(log_ctx->ctx, ",\n");
+ }
+ pkey->algorithm_index = byte_index;
+ pkey->algorithm_length = oid_length;
+ byte_index += oid_length;
+ }
+ }
+
+ if (*decode_error == 0) {
+ /* get parameters, ANY */
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, " Parameters:\n");
+ }
+
+ pkey->parameters_index = byte_index;
+
+ pkey->parameters_length =
+ ptls_asn1_validation_recursive(bytes + byte_index, last_byte1 - byte_index, decode_error, 2, log_ctx);
+
+ byte_index += pkey->parameters_length;
+
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, "\n");
+ }
+ /* close sequence */
+ if (byte_index != last_byte1) {
+ byte_index = ptls_asn1_error_message("Length larger than element", bytes_max, byte_index, 2, log_ctx);
+ *decode_error = PTLS_ERROR_BER_ELEMENT_TOO_SHORT;
+ }
+ }
+
+ /* get octet string, key */
+ if (*decode_error == 0) {
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, last_byte0, byte_index, 0x04, &key_data_length, NULL,
+ &key_data_last, decode_error, log_ctx);
+
+ if (*decode_error == 0) {
+ pkey->key_data_index = byte_index;
+ pkey->key_data_length = key_data_length;
+ byte_index += key_data_length;
+
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, " Key data (%d bytes):\n", key_data_length);
+
+ (void)ptls_asn1_validation_recursive(bytes + pkey->key_data_index, key_data_length, decode_error, 1, log_ctx);
+ log_ctx->fn(log_ctx->ctx, "\n");
+ }
+ }
+ }
+
+ if (*decode_error == 0 && byte_index != last_byte0) {
+ byte_index = ptls_asn1_error_message("Length larger than element", bytes_max, byte_index, 0, log_ctx);
+ *decode_error = PTLS_ERROR_BER_ELEMENT_TOO_SHORT;
+ }
+
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, "\n");
+ }
+
+ return byte_index;
+}
+
+static int ptls_pem_parse_private_key(char const *pem_fname, ptls_asn1_pkcs8_private_key_t *pkey,
+ ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ size_t nb_keys = 0;
+ int ret = ptls_load_pem_objects(pem_fname, "PRIVATE KEY", &pkey->vec, 1, &nb_keys);
+
+ if (ret == 0) {
+ if (nb_keys != 1) {
+ ret = PTLS_ERROR_PEM_LABEL_NOT_FOUND;
+ }
+ }
+
+ if (ret == 0 && nb_keys == 1) {
+ int decode_error = 0;
+
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, "\nFound PRIVATE KEY, length = %d bytes\n", (int)pkey->vec.len);
+ }
+
+ (void)ptls_minicrypto_asn1_decode_private_key(pkey, &decode_error, log_ctx);
+
+ if (decode_error != 0) {
+ ret = decode_error;
+ }
+ }
+
+ return ret;
+}
+
+static const uint8_t ptls_asn1_algorithm_ecdsa[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01};
+
+static const uint8_t ptls_asn1_curve_secp256r1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
+
+static int ptls_set_ecdsa_private_key(ptls_context_t *ctx, ptls_asn1_pkcs8_private_key_t *pkey, ptls_minicrypto_log_ctx_t *log_ctx)
+{
+ uint8_t *bytes = pkey->vec.base + pkey->parameters_index;
+ size_t bytes_max = pkey->parameters_length;
+ size_t byte_index = 0;
+ uint8_t *curve_id = NULL;
+ uint32_t curve_id_length = 0;
+ int decode_error = 0;
+ uint32_t seq_length;
+ size_t last_byte = 0;
+ uint8_t *ecdsa_key_data = NULL;
+ uint32_t ecdsa_key_data_length = 0;
+ size_t ecdsa_key_data_last = 0;
+
+ /* We expect the parameters to include just the curve ID */
+
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, bytes_max, byte_index, 0x06, &curve_id_length, NULL, &last_byte,
+ &decode_error, log_ctx);
+
+ if (decode_error == 0 && bytes_max != last_byte) {
+ byte_index = ptls_asn1_error_message("Length larger than parameters", bytes_max, byte_index, 0, log_ctx);
+ decode_error = PTLS_ERROR_BER_EXCESSIVE_LENGTH;
+ }
+
+ if (decode_error == 0) {
+ curve_id = bytes + byte_index;
+
+ if (log_ctx != NULL) {
+ /* print the OID value */
+ log_ctx->fn(log_ctx->ctx, "Curve: ");
+ ptls_asn1_dump_content(curve_id, curve_id_length, 0, log_ctx);
+ log_ctx->fn(log_ctx->ctx, "\n");
+ }
+ }
+
+ /* We expect the key data to follow the ECDSA structure per RFC 5915 */
+ bytes = pkey->vec.base + pkey->key_data_index;
+ bytes_max = pkey->key_data_length;
+ byte_index = 0;
+
+ /* decode the wrapping sequence */
+ if (decode_error == 0) {
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, bytes_max, byte_index, 0x30, &seq_length, NULL, &last_byte,
+ &decode_error, log_ctx);
+ }
+
+ if (decode_error == 0 && bytes_max != last_byte) {
+ byte_index = ptls_asn1_error_message("Length larger than key data", bytes_max, byte_index, 0, log_ctx);
+ decode_error = PTLS_ERROR_BER_ELEMENT_TOO_SHORT;
+ }
+
+ /* verify and skip the version number 1 */
+ if (decode_error == 0) {
+ /* get first component: version, INTEGER, expect value 0 */
+ if (byte_index + 3 > bytes_max) {
+ byte_index = ptls_asn1_error_message("Cannot find ECDSA Key Data Version", bytes_max, byte_index, 0, log_ctx);
+ decode_error = PTLS_ERROR_INCORRECT_ASN1_ECDSA_KEY_SYNTAX;
+ } else if (bytes[byte_index] != 0x02 || bytes[byte_index + 1] != 0x01 || bytes[byte_index + 2] != 0x01) {
+ decode_error = PTLS_ERROR_INCORRECT_PEM_ECDSA_KEY_VERSION;
+ byte_index = ptls_asn1_error_message("Incorrect ECDSA Key Data Version", bytes_max, byte_index, 0, log_ctx);
+ } else {
+ byte_index += 3;
+ if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, "ECDSA Version = 1,\n");
+ }
+ }
+ }
+
+ /* obtain the octet string that contains the ECDSA private key */
+ if (decode_error == 0) {
+ byte_index = ptls_asn1_get_expected_type_and_length(bytes, last_byte, byte_index, 0x04, &ecdsa_key_data_length, NULL,
+ &ecdsa_key_data_last, &decode_error, log_ctx);
+
+ if (decode_error == 0) {
+ ecdsa_key_data = bytes + byte_index;
+ }
+ }
+
+ /* If everything is fine, associate the ECDSA key with the context */
+ if (curve_id_length == sizeof(ptls_asn1_curve_secp256r1) && curve_id != NULL &&
+ memcmp(curve_id, ptls_asn1_curve_secp256r1, sizeof(ptls_asn1_curve_secp256r1)) == 0) {
+ if (SECP256R1_PRIVATE_KEY_SIZE != ecdsa_key_data_length) {
+ decode_error = PTLS_ERROR_INCORRECT_PEM_ECDSA_KEYSIZE;
+ if (log_ctx != NULL) {
+ /* print the OID value */
+ log_ctx->fn(log_ctx->ctx, "Wrong SECP256R1 key length, %d instead of %d.\n", ecdsa_key_data_length,
+ SECP256R1_PRIVATE_KEY_SIZE);
+ }
+ } else {
+ ptls_minicrypto_secp256r1sha256_sign_certificate_t *minicrypto_sign_certificate;
+
+ minicrypto_sign_certificate = (ptls_minicrypto_secp256r1sha256_sign_certificate_t *)malloc(
+ sizeof(ptls_minicrypto_secp256r1sha256_sign_certificate_t));
+
+ if (minicrypto_sign_certificate == NULL) {
+ decode_error = PTLS_ERROR_NO_MEMORY;
+ } else {
+ memset(minicrypto_sign_certificate, 0, sizeof(ptls_minicrypto_secp256r1sha256_sign_certificate_t));
+ decode_error = ptls_minicrypto_init_secp256r1sha256_sign_certificate(
+ minicrypto_sign_certificate, ptls_iovec_init(ecdsa_key_data, ecdsa_key_data_length));
+ }
+ if (decode_error == 0) {
+ ctx->sign_certificate = &minicrypto_sign_certificate->super;
+
+ if (log_ctx != NULL) {
+ /* print the OID value */
+ log_ctx->fn(log_ctx->ctx, "Initialized SECP512R1 signing key with %d bytes.\n", ecdsa_key_data_length);
+ }
+ } else if (log_ctx != NULL) {
+ log_ctx->fn(log_ctx->ctx, "SECP512R1 init with %d bytes returns %d.\n", ecdsa_key_data_length, decode_error);
+ }
+ }
+ } else {
+ decode_error = PTLS_ERROR_INCORRECT_PEM_ECDSA_CURVE;
+ if (log_ctx != NULL) {
+ /* print the OID value */
+ log_ctx->fn(log_ctx->ctx, "Curve is not supported for signatures.\n");
+ }
+ }
+
+ return decode_error;
+}
+
+int ptls_minicrypto_load_private_key(ptls_context_t *ctx, char const *pem_fname)
+{
+ ptls_asn1_pkcs8_private_key_t pkey = {{0}};
+ int ret = ptls_pem_parse_private_key(pem_fname, &pkey, NULL);
+
+ /* Check that this is the expected key type.
+ * At this point, the minicrypto library only supports ECDSA keys.
+ * In theory, we could add support for RSA keys at some point.
+ */
+ if (ret == 0) {
+ if (pkey.algorithm_length == sizeof(ptls_asn1_algorithm_ecdsa) &&
+ memcmp(pkey.vec.base + pkey.algorithm_index, ptls_asn1_algorithm_ecdsa, sizeof(ptls_asn1_algorithm_ecdsa)) == 0) {
+ ret = ptls_set_ecdsa_private_key(ctx, &pkey, NULL);
+ } else {
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/openssl.c b/web/server/h2o/libh2o/deps/picotls/lib/openssl.c
new file mode 100644
index 00000000..2c9ee700
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/openssl.c
@@ -0,0 +1,1066 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <unistd.h>
+#endif
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/x509_vfy.h>
+#include "picotls.h"
+#include "picotls/openssl.h"
+
+#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define OPENSSL_1_1_API 1
+#elif defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070000fL
+#define OPENSSL_1_1_API 1
+#else
+#define OPENSSL_1_1_API 0
+#endif
+
+#if !OPENSSL_1_1_API
+
+#define EVP_PKEY_up_ref(p) CRYPTO_add(&(p)->references, 1, CRYPTO_LOCK_EVP_PKEY)
+#define X509_STORE_up_ref(p) CRYPTO_add(&(p)->references, 1, CRYPTO_LOCK_X509_STORE)
+
+static HMAC_CTX *HMAC_CTX_new(void)
+{
+ HMAC_CTX *ctx;
+
+ if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL)
+ return NULL;
+ HMAC_CTX_init(ctx);
+ return ctx;
+}
+
+static void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
+#endif
+
+void ptls_openssl_random_bytes(void *buf, size_t len)
+{
+ RAND_bytes(buf, (int)len);
+}
+
+static EC_KEY *ecdh_gerenate_key(EC_GROUP *group)
+{
+ EC_KEY *key;
+
+ if ((key = EC_KEY_new()) == NULL)
+ return NULL;
+ if (!EC_KEY_set_group(key, group) || !EC_KEY_generate_key(key)) {
+ EC_KEY_free(key);
+ return NULL;
+ }
+
+ return key;
+}
+
+static int ecdh_calc_secret(ptls_iovec_t *out, EC_GROUP *group, EC_KEY *privkey, EC_POINT *peer_point)
+{
+ ptls_iovec_t secret;
+ int ret;
+
+ secret.len = (EC_GROUP_get_degree(group) + 7) / 8;
+ if ((secret.base = malloc(secret.len)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if (ECDH_compute_key(secret.base, secret.len, peer_point, privkey, NULL) <= 0) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE; /* ??? */
+ goto Exit;
+ }
+ ret = 0;
+
+Exit:
+ if (ret == 0) {
+ *out = secret;
+ } else {
+ free(secret.base);
+ *out = (ptls_iovec_t){NULL};
+ }
+ return ret;
+}
+
+static EC_POINT *x9_62_decode_point(EC_GROUP *group, ptls_iovec_t vec, BN_CTX *bn_ctx)
+{
+ EC_POINT *point = NULL;
+
+ if ((point = EC_POINT_new(group)) == NULL)
+ return NULL;
+ if (!EC_POINT_oct2point(group, point, vec.base, vec.len, bn_ctx)) {
+ EC_POINT_free(point);
+ return NULL;
+ }
+
+ return point;
+}
+
+static ptls_iovec_t x9_62_encode_point(EC_GROUP *group, const EC_POINT *point, BN_CTX *bn_ctx)
+{
+ ptls_iovec_t vec;
+
+ if ((vec.len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx)) == 0)
+ return (ptls_iovec_t){NULL};
+ if ((vec.base = malloc(vec.len)) == NULL)
+ return (ptls_iovec_t){NULL};
+ if (EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, vec.base, vec.len, bn_ctx) != vec.len) {
+ free(vec.base);
+ return (ptls_iovec_t){NULL};
+ }
+
+ return vec;
+}
+
+struct st_x9_62_keyex_context_t {
+ ptls_key_exchange_context_t super;
+ BN_CTX *bn_ctx;
+ EC_GROUP *group;
+ EC_KEY *privkey;
+ ptls_iovec_t pubkey;
+};
+
+static void x9_62_free_context(struct st_x9_62_keyex_context_t *ctx)
+{
+ free(ctx->pubkey.base);
+ if (ctx->privkey != NULL)
+ EC_KEY_free(ctx->privkey);
+ if (ctx->group != NULL)
+ EC_GROUP_free(ctx->group);
+ if (ctx->bn_ctx != NULL)
+ BN_CTX_free(ctx->bn_ctx);
+ free(ctx);
+}
+
+static int x9_62_on_exchange(ptls_key_exchange_context_t **_ctx, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ struct st_x9_62_keyex_context_t *ctx = (struct st_x9_62_keyex_context_t *)*_ctx;
+ EC_POINT *peer_point = NULL;
+ int ret;
+
+ *_ctx = NULL;
+
+ if ((peer_point = x9_62_decode_point(ctx->group, peerkey, ctx->bn_ctx)) == NULL) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ if ((ret = ecdh_calc_secret(secret, ctx->group, ctx->privkey, peer_point)) != 0)
+ goto Exit;
+
+Exit:
+ if (peer_point != NULL)
+ EC_POINT_free(peer_point);
+ x9_62_free_context(ctx);
+ return ret;
+}
+
+static int x9_62_create_key_exchange(ptls_key_exchange_context_t **_ctx, ptls_iovec_t *pubkey, int nid)
+{
+ struct st_x9_62_keyex_context_t *ctx = NULL;
+ int ret;
+
+ if ((ctx = (struct st_x9_62_keyex_context_t *)malloc(sizeof(*ctx))) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ *ctx = (struct st_x9_62_keyex_context_t){{x9_62_on_exchange}};
+
+ if ((ctx->bn_ctx = BN_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((ctx->group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if ((ctx->privkey = ecdh_gerenate_key(ctx->group)) == NULL) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+
+ if ((ctx->pubkey = x9_62_encode_point(ctx->group, EC_KEY_get0_public_key(ctx->privkey), ctx->bn_ctx)).base == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ *pubkey = ctx->pubkey;
+ ret = 0;
+
+Exit:
+ if (ret == 0) {
+ *_ctx = &ctx->super;
+ } else {
+ if (ctx != NULL)
+ x9_62_free_context(ctx);
+ *_ctx = NULL;
+ *pubkey = (ptls_iovec_t){NULL};
+ }
+
+ return ret;
+}
+
+static int secp256r1_create_key_exchange(ptls_key_exchange_context_t **ctx, ptls_iovec_t *pubkey)
+{
+ return x9_62_create_key_exchange(ctx, pubkey, NID_X9_62_prime256v1);
+}
+
+static int x9_62_key_exchange(EC_GROUP *group, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey, BN_CTX *bn_ctx)
+{
+ EC_POINT *peer_point = NULL;
+ EC_KEY *privkey = NULL;
+ int ret;
+
+ *pubkey = (ptls_iovec_t){NULL};
+ *secret = (ptls_iovec_t){NULL};
+
+ /* decode peer key */
+ if ((peer_point = x9_62_decode_point(group, peerkey, bn_ctx)) == NULL) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+
+ /* create private key */
+ if ((privkey = ecdh_gerenate_key(group)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ /* encode public key */
+ if ((*pubkey = x9_62_encode_point(group, EC_KEY_get0_public_key(privkey), bn_ctx)).base == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ /* calc secret */
+ secret->len = (EC_GROUP_get_degree(group) + 7) / 8;
+ if ((secret->base = malloc(secret->len)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ /* ecdh! */
+ if (ECDH_compute_key(secret->base, secret->len, peer_point, privkey, NULL) <= 0) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE; /* ??? */
+ goto Exit;
+ }
+
+ ret = 0;
+
+Exit:
+ if (peer_point != NULL)
+ EC_POINT_free(peer_point);
+ if (privkey != NULL)
+ EC_KEY_free(privkey);
+ if (ret != 0) {
+ free(pubkey->base);
+ *pubkey = (ptls_iovec_t){NULL};
+ free(secret->base);
+ *secret = (ptls_iovec_t){NULL};
+ }
+ return ret;
+}
+
+static int secp_key_exchange(int nid, ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ EC_GROUP *group = NULL;
+ BN_CTX *bn_ctx = NULL;
+ int ret;
+
+ if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if ((bn_ctx = BN_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ ret = x9_62_key_exchange(group, pubkey, secret, peerkey, bn_ctx);
+
+Exit:
+ if (bn_ctx != NULL)
+ BN_CTX_free(bn_ctx);
+ if (group != NULL)
+ EC_GROUP_free(group);
+ return ret;
+}
+
+static int secp256r1_key_exchange(ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ return secp_key_exchange(NID_X9_62_prime256v1, pubkey, secret, peerkey);
+}
+
+static int do_sign(EVP_PKEY *key, ptls_buffer_t *outbuf, ptls_iovec_t input, const EVP_MD *md)
+{
+ EVP_MD_CTX *ctx = NULL;
+ EVP_PKEY_CTX *pkey_ctx;
+ size_t siglen;
+ int ret;
+
+ if ((ctx = EVP_MD_CTX_create()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if (EVP_DigestSignInit(ctx, &pkey_ctx, md, NULL, key) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_id(key) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ }
+ if (EVP_DigestSignUpdate(ctx, input.base, input.len) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_DigestSignFinal(ctx, NULL, &siglen) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if ((ret = ptls_buffer_reserve(outbuf, siglen)) != 0)
+ goto Exit;
+ if (EVP_DigestSignFinal(ctx, outbuf->base + outbuf->off, &siglen) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ outbuf->off += siglen;
+
+ ret = 0;
+Exit:
+ if (ctx != NULL)
+ EVP_MD_CTX_destroy(ctx);
+ return ret;
+}
+
+struct cipher_context_t {
+ ptls_cipher_context_t super;
+ EVP_CIPHER_CTX *evp;
+};
+
+static void cipher_dispose(ptls_cipher_context_t *_ctx)
+{
+ struct cipher_context_t *ctx = (struct cipher_context_t *)_ctx;
+ EVP_CIPHER_CTX_free(ctx->evp);
+}
+
+static void cipher_do_init(ptls_cipher_context_t *_ctx, const void *iv)
+{
+ struct cipher_context_t *ctx = (struct cipher_context_t *)_ctx;
+ int ret;
+ ret = EVP_EncryptInit_ex(ctx->evp, NULL, NULL, NULL, iv);
+ assert(ret);
+}
+
+static int cipher_setup_crypto(ptls_cipher_context_t *_ctx, const void *key, const EVP_CIPHER *cipher,
+ void (*do_transform)(ptls_cipher_context_t *, void *, const void *, size_t))
+{
+ struct cipher_context_t *ctx = (struct cipher_context_t *)_ctx;
+
+ ctx->super.do_dispose = cipher_dispose;
+ ctx->super.do_init = cipher_do_init;
+ ctx->super.do_transform = do_transform;
+
+ if ((ctx->evp = EVP_CIPHER_CTX_new()) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ if (!EVP_EncryptInit_ex(ctx->evp, cipher, NULL, key, NULL)) {
+ EVP_CIPHER_CTX_free(ctx->evp);
+ return PTLS_ERROR_LIBRARY;
+ }
+
+ return 0;
+}
+
+static void cipher_encrypt(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t _len)
+{
+ struct cipher_context_t *ctx = (struct cipher_context_t *)_ctx;
+ int len = (int)_len, ret = EVP_EncryptUpdate(ctx->evp, output, &len, input, len);
+ assert(ret);
+}
+
+static int aes128ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+ return cipher_setup_crypto(ctx, key, EVP_aes_128_ctr(), cipher_encrypt);
+}
+
+static int aes256ctr_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+ return cipher_setup_crypto(ctx, key, EVP_aes_256_ctr(), cipher_encrypt);
+}
+
+#if defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305)
+
+static int chacha20_setup_crypto(ptls_cipher_context_t *ctx, int is_enc, const void *key)
+{
+ return cipher_setup_crypto(ctx, key, EVP_chacha20(), cipher_encrypt);
+}
+
+#endif
+
+struct aead_crypto_context_t {
+ ptls_aead_context_t super;
+ EVP_CIPHER_CTX *evp_ctx;
+};
+
+static void aead_dispose_crypto(ptls_aead_context_t *_ctx)
+{
+ struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *)_ctx;
+
+ if (ctx->evp_ctx != NULL)
+ EVP_CIPHER_CTX_free(ctx->evp_ctx);
+}
+
+static void aead_do_encrypt_init(ptls_aead_context_t *_ctx, const void *iv, const void *aad, size_t aadlen)
+{
+ struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *)_ctx;
+ int ret;
+
+ /* FIXME for performance, preserve the expanded key instead of the raw key */
+ ret = EVP_EncryptInit_ex(ctx->evp_ctx, NULL, NULL, NULL, iv);
+ assert(ret);
+
+ if (aadlen != 0) {
+ int blocklen;
+ ret = EVP_EncryptUpdate(ctx->evp_ctx, NULL, &blocklen, aad, (int)aadlen);
+ assert(ret);
+ }
+}
+
+static size_t aead_do_encrypt_update(ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen)
+{
+ struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *)_ctx;
+ int blocklen, ret;
+
+ ret = EVP_EncryptUpdate(ctx->evp_ctx, output, &blocklen, input, (int)inlen);
+ assert(ret);
+
+ return blocklen;
+}
+
+static size_t aead_do_encrypt_final(ptls_aead_context_t *_ctx, void *_output)
+{
+ struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *)_ctx;
+ uint8_t *output = _output;
+ size_t off = 0, tag_size = ctx->super.algo->tag_size;
+ int blocklen, ret;
+
+ ret = EVP_EncryptFinal_ex(ctx->evp_ctx, output + off, &blocklen);
+ assert(ret);
+ off += blocklen;
+ ret = EVP_CIPHER_CTX_ctrl(ctx->evp_ctx, EVP_CTRL_GCM_GET_TAG, (int)tag_size, output + off);
+ assert(ret);
+ off += tag_size;
+
+ return off;
+}
+
+static size_t aead_do_decrypt(ptls_aead_context_t *_ctx, void *_output, const void *input, size_t inlen, const void *iv,
+ const void *aad, size_t aadlen)
+{
+ struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *)_ctx;
+ uint8_t *output = _output;
+ size_t off = 0, tag_size = ctx->super.algo->tag_size;
+ int blocklen, ret;
+
+ if (inlen < tag_size)
+ return SIZE_MAX;
+
+ ret = EVP_DecryptInit_ex(ctx->evp_ctx, NULL, NULL, NULL, iv);
+ assert(ret);
+ if (aadlen != 0) {
+ ret = EVP_DecryptUpdate(ctx->evp_ctx, NULL, &blocklen, aad, (int)aadlen);
+ assert(ret);
+ }
+ ret = EVP_DecryptUpdate(ctx->evp_ctx, output + off, &blocklen, input, (int)(inlen - tag_size));
+ assert(ret);
+ off += blocklen;
+ if (!EVP_CIPHER_CTX_ctrl(ctx->evp_ctx, EVP_CTRL_GCM_SET_TAG, (int)tag_size, (void *)((uint8_t *)input + inlen - tag_size)))
+ return SIZE_MAX;
+ if (!EVP_DecryptFinal_ex(ctx->evp_ctx, output + off, &blocklen))
+ return SIZE_MAX;
+ off += blocklen;
+
+ return off;
+}
+
+static int aead_setup_crypto(ptls_aead_context_t *_ctx, int is_enc, const void *key, const EVP_CIPHER *cipher)
+{
+ struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *)_ctx;
+ int ret;
+
+ ctx->super.dispose_crypto = aead_dispose_crypto;
+ if (is_enc) {
+ ctx->super.do_encrypt_init = aead_do_encrypt_init;
+ ctx->super.do_encrypt_update = aead_do_encrypt_update;
+ ctx->super.do_encrypt_final = aead_do_encrypt_final;
+ ctx->super.do_decrypt = NULL;
+ } else {
+ ctx->super.do_encrypt_init = NULL;
+ ctx->super.do_encrypt_update = NULL;
+ ctx->super.do_encrypt_final = NULL;
+ ctx->super.do_decrypt = aead_do_decrypt;
+ }
+ ctx->evp_ctx = NULL;
+
+ if ((ctx->evp_ctx = EVP_CIPHER_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Error;
+ }
+ if (is_enc) {
+ if (!EVP_EncryptInit_ex(ctx->evp_ctx, cipher, NULL, key, NULL)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Error;
+ }
+ } else {
+ if (!EVP_DecryptInit_ex(ctx->evp_ctx, cipher, NULL, key, NULL)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Error;
+ }
+ }
+ if (!EVP_CIPHER_CTX_ctrl(ctx->evp_ctx, EVP_CTRL_GCM_SET_IVLEN, (int)ctx->super.algo->iv_size, NULL)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Error;
+ }
+
+ return 0;
+
+Error:
+ aead_dispose_crypto(&ctx->super);
+ return ret;
+}
+
+static int aead_aes128gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+ return aead_setup_crypto(ctx, is_enc, key, EVP_aes_128_gcm());
+}
+
+static int aead_aes256gcm_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+ return aead_setup_crypto(ctx, is_enc, key, EVP_aes_256_gcm());
+}
+
+#if defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305)
+static int aead_chacha20poly1305_setup_crypto(ptls_aead_context_t *ctx, int is_enc, const void *key)
+{
+ return aead_setup_crypto(ctx, is_enc, key, EVP_chacha20_poly1305());
+}
+#endif
+
+#define _sha256_final(ctx, md) SHA256_Final((md), (ctx))
+ptls_define_hash(sha256, SHA256_CTX, SHA256_Init, SHA256_Update, _sha256_final);
+
+#define _sha384_final(ctx, md) SHA384_Final((md), (ctx))
+ptls_define_hash(sha384, SHA512_CTX, SHA384_Init, SHA384_Update, _sha384_final);
+
+static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, uint16_t *selected_algorithm, ptls_buffer_t *outbuf,
+ ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms)
+{
+ ptls_openssl_sign_certificate_t *self = (ptls_openssl_sign_certificate_t *)_self;
+ const struct st_ptls_openssl_signature_scheme_t *scheme;
+
+ /* select the algorithm */
+ for (scheme = self->schemes; scheme->scheme_id != UINT16_MAX; ++scheme) {
+ size_t i;
+ for (i = 0; i != num_algorithms; ++i)
+ if (algorithms[i] == scheme->scheme_id)
+ goto Found;
+ }
+ return PTLS_ALERT_HANDSHAKE_FAILURE;
+
+Found:
+ *selected_algorithm = scheme->scheme_id;
+ return do_sign(self->key, outbuf, input, scheme->scheme_md);
+}
+
+static X509 *to_x509(ptls_iovec_t vec)
+{
+ const uint8_t *p = vec.base;
+ return d2i_X509(NULL, &p, vec.len);
+}
+
+static int verify_sign(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t signature)
+{
+ EVP_PKEY *key = verify_ctx;
+ EVP_MD_CTX *ctx = NULL;
+ EVP_PKEY_CTX *pkey_ctx = NULL;
+ int ret = 0;
+
+ if (data.base == NULL)
+ goto Exit;
+
+ if ((ctx = EVP_MD_CTX_create()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if (EVP_DigestVerifyInit(ctx, &pkey_ctx, EVP_sha256(), NULL, key) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_id(key) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, -1) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256()) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ }
+ if (EVP_DigestVerifyUpdate(ctx, data.base, data.len) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (EVP_DigestVerifyFinal(ctx, signature.base, signature.len) != 1) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ ret = 0;
+
+Exit:
+ if (ctx != NULL)
+ EVP_MD_CTX_destroy(ctx);
+ EVP_PKEY_free(key);
+ return ret;
+}
+
+int ptls_openssl_init_sign_certificate(ptls_openssl_sign_certificate_t *self, EVP_PKEY *key)
+{
+ *self = (ptls_openssl_sign_certificate_t){{sign_certificate}};
+ size_t scheme_index = 0;
+
+#define PUSH_SCHEME(id, md) \
+ self->schemes[scheme_index++] = (struct st_ptls_openssl_signature_scheme_t) \
+ { \
+ id, md \
+ }
+
+ switch (EVP_PKEY_id(key)) {
+ case EVP_PKEY_RSA:
+ PUSH_SCHEME(PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256, EVP_sha256());
+ PUSH_SCHEME(PTLS_SIGNATURE_RSA_PSS_RSAE_SHA384, EVP_sha384());
+ PUSH_SCHEME(PTLS_SIGNATURE_RSA_PSS_RSAE_SHA512, EVP_sha512());
+ break;
+ case EVP_PKEY_EC: {
+ EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(key);
+ switch (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey))) {
+ case NID_X9_62_prime256v1:
+ PUSH_SCHEME(PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256, EVP_sha256());
+ break;
+#if defined(NID_secp384r1) && !OPENSSL_NO_SHA384
+ case NID_secp384r1:
+ PUSH_SCHEME(PTLS_SIGNATURE_ECDSA_SECP384R1_SHA384, EVP_sha384());
+ break;
+#endif
+#if defined(NID_secp384r1) && !OPENSSL_NO_SHA512
+ case NID_secp521r1:
+ PUSH_SCHEME(PTLS_SIGNATURE_ECDSA_SECP521R1_SHA512, EVP_sha512());
+ break;
+#endif
+ default:
+ EC_KEY_free(eckey);
+ return PTLS_ERROR_INCOMPATIBLE_KEY;
+ }
+ EC_KEY_free(eckey);
+ } break;
+ default:
+ return PTLS_ERROR_INCOMPATIBLE_KEY;
+ }
+ PUSH_SCHEME(UINT16_MAX, NULL);
+ assert(scheme_index <= sizeof(self->schemes) / sizeof(self->schemes[0]));
+
+#undef PUSH_SCHEME
+
+ EVP_PKEY_up_ref(key);
+ self->key = key;
+
+ return 0;
+}
+
+void ptls_openssl_dispose_sign_certificate(ptls_openssl_sign_certificate_t *self)
+{
+ EVP_PKEY_free(self->key);
+}
+
+static int serialize_cert(X509 *cert, ptls_iovec_t *dst)
+{
+ int len = i2d_X509(cert, NULL);
+ assert(len > 0);
+
+ if ((dst->base = malloc(len)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ unsigned char *p = dst->base;
+ dst->len = i2d_X509(cert, &p);
+ assert(len == dst->len);
+
+ return 0;
+}
+
+int ptls_openssl_load_certificates(ptls_context_t *ctx, X509 *cert, STACK_OF(X509) * chain)
+{
+ ptls_iovec_t *list = NULL;
+ size_t slot = 0, count = (cert != NULL) + (chain != NULL ? sk_X509_num(chain) : 0);
+ int ret;
+
+ assert(ctx->certificates.list == NULL);
+
+ if ((list = malloc(sizeof(*list) * count)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if (cert != NULL) {
+ if ((ret = serialize_cert(cert, list + slot++)) != 0)
+ goto Exit;
+ }
+ if (chain != NULL) {
+ int i;
+ for (i = 0; i != sk_X509_num(chain); ++i) {
+ if ((ret = serialize_cert(sk_X509_value(chain, i), list + slot++)) != 0)
+ goto Exit;
+ }
+ }
+
+ assert(slot == count);
+
+ ctx->certificates.list = list;
+ ctx->certificates.count = count;
+ ret = 0;
+
+Exit:
+ if (ret != 0 && list != NULL) {
+ size_t i;
+ for (i = 0; i != slot; ++i)
+ free(list[i].base);
+ free(list);
+ }
+ return ret;
+}
+
+static int verify_certificate(ptls_verify_certificate_t *_self, ptls_t *tls, int (**verifier)(void *, ptls_iovec_t, ptls_iovec_t),
+ void **verify_data, ptls_iovec_t *certs, size_t num_certs)
+{
+ ptls_openssl_verify_certificate_t *self = (ptls_openssl_verify_certificate_t *)_self;
+ X509 *cert = NULL;
+ STACK_OF(X509) *chain = NULL;
+ X509_STORE_CTX *verify_ctx = NULL;
+ int ret = 0;
+
+ assert(num_certs != 0);
+
+ if ((cert = to_x509(certs[0])) == NULL) {
+ ret = PTLS_ALERT_BAD_CERTIFICATE;
+ goto Exit;
+ }
+
+ if (self->cert_store != NULL) {
+ size_t i;
+ for (i = 1; i != num_certs; ++i) {
+ X509 *interm = to_x509(certs[i]);
+ if (interm == NULL) {
+ ret = PTLS_ALERT_BAD_CERTIFICATE;
+ goto Exit;
+ }
+ }
+ if ((verify_ctx = X509_STORE_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if (X509_STORE_CTX_init(verify_ctx, self->cert_store, cert, chain) != 1) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ X509_STORE_CTX_set_purpose(verify_ctx, X509_PURPOSE_SSL_CLIENT);
+ if (X509_verify_cert(verify_ctx) == 1) {
+ ret = 0;
+ } else {
+ switch (X509_STORE_CTX_get_error(verify_ctx)) {
+ case X509_V_ERR_OUT_OF_MEM:
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ case X509_V_ERR_CERT_REVOKED:
+ ret = PTLS_ALERT_CERTIFICATE_REVOKED;
+ goto Exit;
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ ret = PTLS_ALERT_CERTIFICATE_EXPIRED;
+ goto Exit;
+ default:
+ ret = PTLS_ALERT_CERTIFICATE_UNKNOWN;
+ goto Exit;
+ }
+ }
+ }
+
+ if ((*verify_data = X509_get_pubkey(cert)) == NULL) {
+ ret = PTLS_ALERT_BAD_CERTIFICATE;
+ goto Exit;
+ }
+ *verifier = verify_sign;
+
+Exit:
+ if (verify_ctx != NULL)
+ X509_STORE_CTX_free(verify_ctx);
+ if (chain != NULL)
+ sk_X509_free(chain);
+ if (cert != NULL)
+ X509_free(cert);
+ return ret;
+}
+
+int ptls_openssl_init_verify_certificate(ptls_openssl_verify_certificate_t *self, X509_STORE *store)
+{
+ *self = (ptls_openssl_verify_certificate_t){{verify_certificate}};
+
+ if (store != NULL) {
+ if (store != PTLS_OPENSSL_DEFAULT_CERTIFICATE_STORE) {
+ X509_STORE_up_ref(store);
+ self->cert_store = store;
+ } else {
+ X509_LOOKUP *lookup;
+ if ((self->cert_store = X509_STORE_new()) == NULL)
+ return -1;
+ if ((lookup = X509_STORE_add_lookup(self->cert_store, X509_LOOKUP_file())) == NULL)
+ return -1;
+ X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+ if ((lookup = X509_STORE_add_lookup(self->cert_store, X509_LOOKUP_hash_dir())) == NULL)
+ return -1;
+ X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+ }
+ }
+
+ return 0;
+}
+
+void ptls_openssl_dispose_verify_certificate(ptls_openssl_verify_certificate_t *self)
+{
+ X509_STORE_free(self->cert_store);
+ free(self);
+}
+
+#define TICKET_LABEL_SIZE 16
+#define TICKET_IV_SIZE EVP_MAX_IV_LENGTH
+
+int ptls_openssl_encrypt_ticket(ptls_buffer_t *buf, ptls_iovec_t src,
+ int (*cb)(unsigned char *key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc))
+{
+ EVP_CIPHER_CTX *cctx = NULL;
+ HMAC_CTX *hctx = NULL;
+ uint8_t *dst;
+ int clen, ret;
+
+ if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((hctx = HMAC_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ if ((ret = ptls_buffer_reserve(buf, TICKET_LABEL_SIZE + TICKET_IV_SIZE + src.len + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE)) !=
+ 0)
+ goto Exit;
+ dst = buf->base + buf->off;
+
+ /* fill label and iv, as well as obtaining the keys */
+ if (!(*cb)(dst, dst + TICKET_LABEL_SIZE, cctx, hctx, 1)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ dst += TICKET_LABEL_SIZE + TICKET_IV_SIZE;
+
+ /* encrypt */
+ if (!EVP_EncryptUpdate(cctx, dst, &clen, src.base, (int)src.len)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ dst += clen;
+ if (!EVP_EncryptFinal_ex(cctx, dst, &clen)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ dst += clen;
+
+ /* append hmac */
+ if (!HMAC_Update(hctx, buf->base + buf->off, dst - (buf->base + buf->off)) || !HMAC_Final(hctx, dst, NULL)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ dst += HMAC_size(hctx);
+
+ assert(dst <= buf->base + buf->capacity);
+ buf->off += dst - (buf->base + buf->off);
+ ret = 0;
+
+Exit:
+ if (cctx != NULL)
+ EVP_CIPHER_CTX_cleanup(cctx);
+ if (hctx != NULL)
+ HMAC_CTX_free(hctx);
+ return ret;
+}
+
+int ptls_openssl_decrypt_ticket(ptls_buffer_t *buf, ptls_iovec_t src,
+ int (*cb)(unsigned char *key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc))
+{
+ EVP_CIPHER_CTX *cctx = NULL;
+ HMAC_CTX *hctx = NULL;
+ int clen, ret;
+
+ if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((hctx = HMAC_CTX_new()) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ /* obtain cipher and hash context.
+ * Note: no need to handle renew, since in picotls we always send a new ticket to minimize the chance of ticket reuse */
+ if (src.len < TICKET_LABEL_SIZE + TICKET_IV_SIZE) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ if (!(*cb)(src.base, src.base + TICKET_LABEL_SIZE, cctx, hctx, 0)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+
+ /* check hmac, and exclude label, iv, hmac */
+ size_t hmac_size = HMAC_size(hctx);
+ if (src.len < TICKET_LABEL_SIZE + TICKET_IV_SIZE + hmac_size) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ src.len -= hmac_size;
+ uint8_t hmac[EVP_MAX_MD_SIZE];
+ if (!HMAC_Update(hctx, src.base, src.len) || !HMAC_Final(hctx, hmac, NULL)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ if (memcmp(src.base + src.len, hmac, hmac_size) != 0) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ src.base += TICKET_LABEL_SIZE + TICKET_IV_SIZE;
+ src.len -= TICKET_LABEL_SIZE + TICKET_IV_SIZE;
+
+ /* decrypt */
+ if ((ret = ptls_buffer_reserve(buf, src.len)) != 0)
+ goto Exit;
+ if (!EVP_DecryptUpdate(cctx, buf->base + buf->off, &clen, src.base, (int)src.len)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ buf->off += clen;
+ if (!EVP_DecryptFinal_ex(cctx, buf->base + buf->off, &clen)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ buf->off += clen;
+
+ ret = 0;
+
+Exit:
+ if (cctx != NULL)
+ EVP_CIPHER_CTX_cleanup(cctx);
+ if (hctx != NULL)
+ HMAC_CTX_free(hctx);
+ return ret;
+}
+
+ptls_key_exchange_algorithm_t ptls_openssl_secp256r1 = {PTLS_GROUP_SECP256R1, secp256r1_create_key_exchange,
+ secp256r1_key_exchange};
+ptls_key_exchange_algorithm_t *ptls_openssl_key_exchanges[] = {&ptls_openssl_secp256r1, NULL};
+ptls_cipher_algorithm_t ptls_openssl_aes128ctr = {"AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_IV_SIZE,
+ sizeof(struct cipher_context_t), aes128ctr_setup_crypto};
+ptls_aead_algorithm_t ptls_openssl_aes128gcm = {"AES128-GCM",
+ &ptls_openssl_aes128ctr,
+ PTLS_AES128_KEY_SIZE,
+ PTLS_AESGCM_IV_SIZE,
+ PTLS_AESGCM_TAG_SIZE,
+ sizeof(struct aead_crypto_context_t),
+ aead_aes128gcm_setup_crypto};
+ptls_cipher_algorithm_t ptls_openssl_aes256ctr = {"AES256-CTR", PTLS_AES256_KEY_SIZE, PTLS_AES_IV_SIZE,
+ sizeof(struct cipher_context_t), aes256ctr_setup_crypto};
+ptls_aead_algorithm_t ptls_openssl_aes256gcm = {"AES256-GCM",
+ &ptls_openssl_aes256ctr,
+ PTLS_AES256_KEY_SIZE,
+ PTLS_AESGCM_IV_SIZE,
+ PTLS_AESGCM_TAG_SIZE,
+ sizeof(struct aead_crypto_context_t),
+ aead_aes256gcm_setup_crypto};
+ptls_hash_algorithm_t ptls_openssl_sha256 = {PTLS_SHA256_BLOCK_SIZE, PTLS_SHA256_DIGEST_SIZE, sha256_create,
+ PTLS_ZERO_DIGEST_SHA256};
+ptls_hash_algorithm_t ptls_openssl_sha384 = {PTLS_SHA384_BLOCK_SIZE, PTLS_SHA384_DIGEST_SIZE, sha384_create,
+ PTLS_ZERO_DIGEST_SHA384};
+ptls_cipher_suite_t ptls_openssl_aes128gcmsha256 = {PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, &ptls_openssl_aes128gcm,
+ &ptls_openssl_sha256};
+ptls_cipher_suite_t ptls_openssl_aes256gcmsha384 = {PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, &ptls_openssl_aes256gcm,
+ &ptls_openssl_sha384};
+#if defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305)
+ptls_cipher_algorithm_t ptls_openssl_chacha20 = {"CHACHA20", PTLS_CHACHA20_KEY_SIZE, PTLS_CHACHA20_IV_SIZE,
+ sizeof(struct cipher_context_t), chacha20_setup_crypto};
+ptls_aead_algorithm_t ptls_openssl_chacha20poly1305 = {"CHACHA20-POLY1305",
+ &ptls_openssl_chacha20,
+ PTLS_CHACHA20_KEY_SIZE,
+ PTLS_CHACHA20POLY1305_IV_SIZE,
+ PTLS_CHACHA20POLY1305_TAG_SIZE,
+ sizeof(struct aead_crypto_context_t),
+ aead_chacha20poly1305_setup_crypto};
+ptls_cipher_suite_t ptls_openssl_chacha20poly1305sha256 = {PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256,
+ &ptls_openssl_chacha20poly1305, &ptls_openssl_sha256};
+#endif
+ptls_cipher_suite_t *ptls_openssl_cipher_suites[] = {&ptls_openssl_aes256gcmsha384, &ptls_openssl_aes128gcmsha256,
+#if defined(PTLS_OPENSSL_HAVE_CHACHA20_POLY1305)
+ &ptls_openssl_chacha20poly1305sha256,
+#endif
+ NULL};
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/pembase64.c b/web/server/h2o/libh2o/deps/picotls/lib/pembase64.c
new file mode 100644
index 00000000..de44c538
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/pembase64.c
@@ -0,0 +1,373 @@
+/*
+* Copyright (c) 2016 Christian Huitema <huitema@huitema.net>
+*
+* Permission to use, copy, modify, and distribute this software for any
+* purpose with or without fee is hereby granted, provided that the above
+* copyright notice and this permission notice appear in all copies.
+*
+* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Manage Base64 encoding.
+ */
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <sys/time.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "picotls.h"
+#include "picotls/pembase64.h"
+
+static char ptls_base64_alphabet[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
+
+static char ptls_base64_values[] = {
+ /* 0x00 to 0x0F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 0x10 to 0x1F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 0x20 to 0x2F. '+' at 2B, '/' at 2F */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ /* 0x30 to 0x3F -- digits 0 to 9 at 0x30 to 0x39*/
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ /* 0x40 to 0x4F -- chars 'A' to 'O' at 0x41 to 0x4F */
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ /* 0x50 to 0x5F -- chars 'P' to 'Z' at 0x50 to 0x5A */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ /* 0x60 to 0x6F -- chars 'a' to 'o' at 0x61 to 0x6F */
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ /* 0x70 to 0x7F -- chars 'p' to 'z' at 0x70 to 0x7A */
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1};
+
+static void ptls_base64_cell(const uint8_t *data, char *text)
+{
+ int n[4];
+
+ n[0] = data[0] >> 2;
+ n[1] = ((data[0] & 3) << 4) | (data[1] >> 4);
+ n[2] = ((data[1] & 15) << 2) | (data[2] >> 6);
+ n[3] = data[2] & 63;
+
+ for (int i = 0; i < 4; i++) {
+ text[i] = ptls_base64_alphabet[n[i]];
+ }
+}
+
+size_t ptls_base64_howlong(size_t data_length)
+{
+ return (((data_length + 2) / 3) * 4);
+}
+
+int ptls_base64_encode(const uint8_t *data, size_t data_len, char *ptls_base64_text)
+{
+ int l = 0;
+ int lt = 0;
+
+ while ((data_len - l) >= 3) {
+ ptls_base64_cell(data + l, ptls_base64_text + lt);
+ l += 3;
+ lt += 4;
+ }
+
+ switch (data_len - l) {
+ case 0:
+ break;
+ case 1:
+ ptls_base64_text[lt++] = ptls_base64_alphabet[data[l] >> 2];
+ ptls_base64_text[lt++] = ptls_base64_alphabet[(data[l] & 3) << 4];
+ ptls_base64_text[lt++] = '=';
+ ptls_base64_text[lt++] = '=';
+ break;
+ case 2:
+ ptls_base64_text[lt++] = ptls_base64_alphabet[data[l] >> 2];
+ ptls_base64_text[lt++] = ptls_base64_alphabet[((data[l] & 3) << 4) | (data[l + 1] >> 4)];
+ ptls_base64_text[lt++] = ptls_base64_alphabet[((data[l + 1] & 15) << 2)];
+ ptls_base64_text[lt++] = '=';
+ break;
+ default:
+ break;
+ }
+ ptls_base64_text[lt++] = 0;
+
+ return lt;
+}
+
+/*
+ * Take into input a line of text, so as to work by increments.
+ * The intermediate text of the decoding is kept in a state variable.
+ * The decoded data is accumulated in a PTLS buffer.
+ * The parsing is consistent with the lax definition in RFC 7468
+ */
+
+void ptls_base64_decode_init(ptls_base64_decode_state_t *state)
+{
+ state->nbc = 0;
+ state->nbo = 3;
+ state->v = 0;
+ state->status = PTLS_BASE64_DECODE_IN_PROGRESS;
+}
+
+int ptls_base64_decode(const char *text, ptls_base64_decode_state_t *state, ptls_buffer_t *buf)
+{
+ int ret = 0;
+ uint8_t decoded[3];
+ size_t text_index = 0;
+ int c;
+ char vc;
+
+ /* skip initial blanks */
+ while (text[text_index] != 0) {
+ c = text[text_index];
+
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ text_index++;
+ } else {
+ break;
+ }
+ }
+
+ while (text[text_index] != 0 && ret == 0 && state->status == PTLS_BASE64_DECODE_IN_PROGRESS) {
+ c = text[text_index++];
+
+ vc = 0 < c && c < 0x7f ? ptls_base64_values[c] : -1;
+ if (vc == -1) {
+ if (state->nbc == 2 && c == '=' && text[text_index] == '=') {
+ state->nbc = 4;
+ text_index++;
+ state->nbo = 1;
+ state->v <<= 12;
+ } else if (state->nbc == 3 && c == '=') {
+ state->nbc = 4;
+ state->nbo = 2;
+ state->v <<= 6;
+ } else {
+ /* Skip final blanks */
+ text_index--;
+ while (text[text_index] != 0) {
+ c = text[text_index++];
+
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0x0B || c == 0x0C) {
+ continue;
+ }
+ }
+
+ /* Should now be at end of buffer */
+ if (text[text_index] == 0) {
+ break;
+ } else {
+ /* Not at end of buffer, signal a decoding error */
+ state->nbo = 0;
+ state->status = PTLS_BASE64_DECODE_FAILED;
+ ret = PTLS_ERROR_INCORRECT_BASE64;
+ }
+ }
+ } else {
+ state->nbc++;
+ state->v <<= 6;
+ state->v |= vc;
+ }
+
+ if (ret == 0 && state->nbc == 4) {
+ /* Convert to up to 3 octets */
+ for (int j = 0; j < state->nbo; j++) {
+ decoded[j] = (uint8_t)(state->v >> (8 * (2 - j)));
+ }
+
+ ret = ptls_buffer__do_pushv(buf, decoded, state->nbo);
+
+ if (ret == 0) {
+ /* test for fin or continuation */
+ if (state->nbo < 3) {
+ /* Check that there are only trainling blanks on this line */
+ while (text[text_index] != 0) {
+ c = text[text_index++];
+
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0x0B || c == 0x0C) {
+ continue;
+ }
+ }
+ if (text[text_index] == 0) {
+ state->status = PTLS_BASE64_DECODE_DONE;
+ } else {
+ state->status = PTLS_BASE64_DECODE_FAILED;
+ ret = PTLS_ERROR_INCORRECT_BASE64;
+ }
+ break;
+ } else {
+ state->v = 0;
+ state->nbo = 3;
+ state->nbc = 0;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ * Reading a PEM file, to get an object:
+ *
+ * - Find first object, get the object name.
+ * - If object label is what the application expects, parse, else skip to end.
+ *
+ * The following labels are defined in RFC 7468:
+ *
+ * Sec. Label ASN.1 Type Reference Module
+ * ----+----------------------+-----------------------+---------+----------
+ * 5 CERTIFICATE Certificate [RFC5280] id-pkix1-e
+ * 6 X509 CRL CertificateList [RFC5280] id-pkix1-e
+ * 7 CERTIFICATE REQUEST CertificationRequest [RFC2986] id-pkcs10
+ * 8 PKCS7 ContentInfo [RFC2315] id-pkcs7*
+ * 9 CMS ContentInfo [RFC5652] id-cms2004
+ * 10 PRIVATE KEY PrivateKeyInfo ::= [RFC5208] id-pkcs8
+ * OneAsymmetricKey [RFC5958] id-aKPV1
+ * 11 ENCRYPTED PRIVATE KEY EncryptedPrivateKeyInfo [RFC5958] id-aKPV1
+ * 12 ATTRIBUTE CERTIFICATE AttributeCertificate [RFC5755] id-acv2
+ * 13 PUBLIC KEY SubjectPublicKeyInfo [RFC5280] id-pkix1-e
+ */
+
+static int ptls_compare_separator_line(const char *line, const char *begin_or_end, const char *label)
+{
+ int ret = strncmp(line, "-----", 5);
+ size_t text_index = 5;
+
+ if (ret == 0) {
+ size_t begin_or_end_length = strlen(begin_or_end);
+ ret = strncmp(line + text_index, begin_or_end, begin_or_end_length);
+ text_index += begin_or_end_length;
+ }
+
+ if (ret == 0) {
+ ret = line[text_index] - ' ';
+ text_index++;
+ }
+
+ if (ret == 0) {
+ size_t label_length = strlen(label);
+ ret = strncmp(line + text_index, label, label_length);
+ text_index += label_length;
+ }
+
+ if (ret == 0) {
+ ret = strncmp(line + text_index, "-----", 5);
+ }
+
+ return ret;
+}
+
+static int ptls_get_pem_object(FILE *F, const char *label, ptls_buffer_t *buf)
+{
+ int ret = PTLS_ERROR_PEM_LABEL_NOT_FOUND;
+ char line[256];
+ ptls_base64_decode_state_t state;
+
+ /* Get the label on a line by itself */
+ while (fgets(line, 256, F)) {
+ if (ptls_compare_separator_line(line, "BEGIN", label) == 0) {
+ ret = 0;
+ ptls_base64_decode_init(&state);
+ break;
+ }
+ }
+ /* Get the data in the buffer */
+ while (ret == 0 && fgets(line, 256, F)) {
+ if (ptls_compare_separator_line(line, "END", label) == 0) {
+ if (state.status == PTLS_BASE64_DECODE_DONE || (state.status == PTLS_BASE64_DECODE_IN_PROGRESS && state.nbc == 0)) {
+ ret = 0;
+ } else {
+ ret = PTLS_ERROR_INCORRECT_BASE64;
+ }
+ break;
+ } else {
+ ret = ptls_base64_decode(line, &state, buf);
+ }
+ }
+
+ return ret;
+}
+
+int ptls_load_pem_objects(char const *pem_fname, const char *label, ptls_iovec_t *list, size_t list_max, size_t *nb_objects)
+{
+ FILE *F;
+ int ret = 0;
+ size_t count = 0;
+#ifdef _WINDOWS
+ errno_t err = fopen_s(&F, pem_fname, "r");
+ if (err != 0) {
+ ret = -1;
+ }
+#else
+ F = fopen(pem_fname, "r");
+ if (F == NULL) {
+ ret = -1;
+ }
+#endif
+
+ *nb_objects = 0;
+
+ if (ret == 0) {
+ while (count < list_max) {
+ ptls_buffer_t buf;
+
+ ptls_buffer_init(&buf, "", 0);
+
+ ret = ptls_get_pem_object(F, label, &buf);
+
+ if (ret == 0) {
+ if (buf.off > 0 && buf.is_allocated) {
+ list[count].base = buf.base;
+ list[count].len = buf.off;
+ count++;
+ } else {
+ ptls_buffer_dispose(&buf);
+ }
+ } else {
+ ptls_buffer_dispose(&buf);
+ break;
+ }
+ }
+ }
+
+ if (ret == PTLS_ERROR_PEM_LABEL_NOT_FOUND && count > 0) {
+ ret = 0;
+ }
+
+ *nb_objects = count;
+
+ if (F != NULL) {
+ fclose(F);
+ }
+
+ return ret;
+}
+
+#define PTLS_MAX_CERTS_IN_CONTEXT 16
+
+int ptls_load_certificates(ptls_context_t *ctx, char *cert_pem_file)
+{
+ int ret = 0;
+
+ ctx->certificates.list = (ptls_iovec_t *)malloc(PTLS_MAX_CERTS_IN_CONTEXT * sizeof(ptls_iovec_t));
+
+ if (ctx->certificates.list == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ } else {
+ ret = ptls_load_pem_objects(cert_pem_file, "CERTIFICATE", ctx->certificates.list, PTLS_MAX_CERTS_IN_CONTEXT,
+ &ctx->certificates.count);
+ }
+
+ return ret;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/picotls.c b/web/server/h2o/libh2o/deps/picotls/lib/picotls.c
new file mode 100644
index 00000000..d328aaac
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/picotls.c
@@ -0,0 +1,3761 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <sys/time.h>
+#endif
+#include "picotls.h"
+
+#define PTLS_MAX_PLAINTEXT_RECORD_SIZE 16384
+#define PTLS_MAX_ENCRYPTED_RECORD_SIZE (16384 + 256)
+
+#define PTLS_RECORD_VERSION_MAJOR 3
+#define PTLS_RECORD_VERSION_MINOR 3
+
+#define PTLS_HELLO_RANDOM_SIZE 32
+
+#define PTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC 20
+#define PTLS_CONTENT_TYPE_ALERT 21
+#define PTLS_CONTENT_TYPE_HANDSHAKE 22
+#define PTLS_CONTENT_TYPE_APPDATA 23
+
+#define PTLS_HANDSHAKE_TYPE_CLIENT_HELLO 1
+#define PTLS_HANDSHAKE_TYPE_SERVER_HELLO 2
+#define PTLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET 4
+#define PTLS_HANDSHAKE_TYPE_END_OF_EARLY_DATA 5
+#define PTLS_HANDSHAKE_TYPE_ENCRYPTED_EXTENSIONS 8
+#define PTLS_HANDSHAKE_TYPE_CERTIFICATE 11
+#define PTLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST 13
+#define PTLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY 15
+#define PTLS_HANDSHAKE_TYPE_FINISHED 20
+#define PTLS_HANDSHAKE_TYPE_KEY_UPDATE 24
+#define PTLS_HANDSHAKE_TYPE_MESSAGE_HASH 254
+
+#define PTLS_PSK_KE_MODE_PSK 0
+#define PTLS_PSK_KE_MODE_PSK_DHE 1
+
+#define PTLS_HANDSHAKE_HEADER_SIZE 4
+
+#define PTLS_EXTENSION_TYPE_SERVER_NAME 0
+#define PTLS_EXTENSION_TYPE_STATUS_REQUEST 5
+#define PTLS_EXTENSION_TYPE_SUPPORTED_GROUPS 10
+#define PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS 13
+#define PTLS_EXTENSION_TYPE_ALPN 16
+#define PTLS_EXTENSION_TYPE_PRE_SHARED_KEY 41
+#define PTLS_EXTENSION_TYPE_EARLY_DATA 42
+#define PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS 43
+#define PTLS_EXTENSION_TYPE_COOKIE 44
+#define PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES 45
+#define PTLS_EXTENSION_TYPE_KEY_SHARE 51
+
+#define PTLS_PROTOCOL_VERSION_DRAFT26 0x7f1a
+#define PTLS_PROTOCOL_VERSION_DRAFT27 0x7f1b
+#define PTLS_PROTOCOL_VERSION_DRAFT28 0x7f1c
+
+#define PTLS_SERVER_NAME_TYPE_HOSTNAME 0
+
+#define PTLS_SERVER_CERTIFICATE_VERIFY_CONTEXT_STRING "TLS 1.3, server CertificateVerify"
+#define PTLS_CLIENT_CERTIFICATE_VERIFY_CONTEXT_STRING "TLS 1.3, client CertificateVerify"
+#define PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE \
+ (64 + sizeof(PTLS_SERVER_CERTIFICATE_VERIFY_CONTEXT_STRING) + PTLS_MAX_DIGEST_SIZE * 2)
+
+#define PTLS_EARLY_DATA_MAX_DELAY 10000 /* max. RTT (in msec) to permit early data */
+
+#if defined(PTLS_DEBUG) && PTLS_DEBUG
+#define PTLS_DEBUGF(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define PTLS_DEBUGF(...)
+#endif
+
+#ifndef PTLS_MEMORY_DEBUG
+#define PTLS_MEMORY_DEBUG 0
+#endif
+
+/**
+ * list of supported versions in the preferred order
+ */
+static const uint16_t supported_versions[] = {PTLS_PROTOCOL_VERSION_DRAFT28, PTLS_PROTOCOL_VERSION_DRAFT27,
+ PTLS_PROTOCOL_VERSION_DRAFT26};
+
+static const uint8_t hello_retry_random[PTLS_HELLO_RANDOM_SIZE] = {0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C,
+ 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB,
+ 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C};
+
+struct st_ptls_traffic_protection_t {
+ uint8_t secret[PTLS_MAX_DIGEST_SIZE];
+ ptls_aead_context_t *aead;
+ uint64_t seq;
+};
+
+struct st_ptls_early_data_t {
+ uint8_t next_secret[PTLS_MAX_DIGEST_SIZE];
+};
+
+struct st_ptls_t {
+ /**
+ * the context
+ */
+ ptls_context_t *ctx;
+ /**
+ * the state
+ */
+ enum {
+ PTLS_STATE_CLIENT_HANDSHAKE_START,
+ PTLS_STATE_CLIENT_EXPECT_SERVER_HELLO,
+ PTLS_STATE_CLIENT_EXPECT_SECOND_SERVER_HELLO,
+ PTLS_STATE_CLIENT_EXPECT_ENCRYPTED_EXTENSIONS,
+ PTLS_STATE_CLIENT_EXPECT_CERTIFICATE,
+ PTLS_STATE_CLIENT_EXPECT_CERTIFICATE_VERIFY,
+ PTLS_STATE_CLIENT_EXPECT_FINISHED,
+ PTLS_STATE_SERVER_EXPECT_CLIENT_HELLO,
+ PTLS_STATE_SERVER_EXPECT_SECOND_CLIENT_HELLO,
+ /* ptls_send can be called if the state is below here */
+ PTLS_STATE_SERVER_EXPECT_END_OF_EARLY_DATA,
+ PTLS_STATE_SERVER_EXPECT_FINISHED,
+ PTLS_STATE_POST_HANDSHAKE_MIN,
+ PTLS_STATE_CLIENT_POST_HANDSHAKE = PTLS_STATE_POST_HANDSHAKE_MIN,
+ PTLS_STATE_SERVER_POST_HANDSHAKE
+ } state;
+ /**
+ * receive buffers
+ */
+ struct {
+ ptls_buffer_t rec;
+ ptls_buffer_t mess;
+ } recvbuf;
+ /**
+ * key schedule
+ */
+ struct st_ptls_key_schedule_t *key_schedule;
+ /**
+ * values used for record protection
+ */
+ struct {
+ struct st_ptls_traffic_protection_t dec;
+ struct st_ptls_traffic_protection_t enc;
+ } traffic_protection;
+ /**
+ * server-name passed using SNI
+ */
+ char *server_name;
+ /**
+ * result of ALPN
+ */
+ char *negotiated_protocol;
+ /**
+ * selected key-exchange
+ */
+ ptls_key_exchange_algorithm_t *key_share;
+ /**
+ * selected cipher-suite
+ */
+ ptls_cipher_suite_t *cipher_suite;
+ /**
+ * clienthello.random
+ */
+ uint8_t client_random[PTLS_HELLO_RANDOM_SIZE];
+ /* flags */
+ unsigned is_server : 1;
+ unsigned is_psk_handshake : 1;
+ unsigned skip_early_data : 1; /* if early-data is not recognized by the server */
+ unsigned send_change_cipher_spec : 1;
+ /**
+ * exporter master secret (either 0rtt or 1rtt)
+ */
+ struct {
+ uint8_t *early;
+ uint8_t *one_rtt;
+ } exporter_master_secret;
+ /**
+ * misc.
+ */
+ union {
+ struct {
+ uint8_t legacy_session_id[16];
+ ptls_key_exchange_context_t *key_share_ctx;
+ struct {
+ int (*cb)(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t signature);
+ void *verify_ctx;
+ } certificate_verify;
+ unsigned offered_psk : 1;
+ } client;
+ struct {
+ uint8_t pending_traffic_secret[PTLS_MAX_DIGEST_SIZE];
+ } server;
+ };
+ /**
+ * the value contains the traffic secret to be commisioned after END_OF_EARLY_DATA
+ * END_OF_EARLY_DATA
+ */
+ struct st_ptls_early_data_t *early_data;
+ /**
+ * user data
+ */
+ void *data_ptr;
+};
+
+struct st_ptls_record_t {
+ uint8_t type;
+ uint16_t version;
+ size_t length;
+ const uint8_t *fragment;
+};
+
+struct st_ptls_client_hello_psk_t {
+ ptls_iovec_t identity;
+ uint32_t obfuscated_ticket_age;
+ ptls_iovec_t binder;
+};
+
+#define MAX_UNKNOWN_EXTENSIONS 16
+
+struct st_ptls_client_hello_t {
+ const uint8_t *random_bytes;
+ ptls_iovec_t legacy_session_id;
+ struct {
+ const uint8_t *ids;
+ size_t count;
+ } compression_methods;
+ uint16_t selected_version;
+ ptls_iovec_t cipher_suites;
+ ptls_iovec_t negotiated_groups;
+ ptls_iovec_t key_shares;
+ struct {
+ uint16_t list[16]; /* expand? */
+ size_t count;
+ } signature_algorithms;
+ ptls_iovec_t server_name;
+ struct {
+ ptls_iovec_t list[16];
+ size_t count;
+ } alpn;
+ struct {
+ ptls_iovec_t all;
+ ptls_iovec_t tbs;
+ ptls_iovec_t ch1_hash;
+ ptls_iovec_t signature;
+ unsigned sent_key_share : 1;
+ } cookie;
+ struct {
+ const uint8_t *hash_end;
+ struct {
+ struct st_ptls_client_hello_psk_t list[4];
+ size_t count;
+ } identities;
+ unsigned ke_modes;
+ int early_data_indication;
+ } psk;
+ ptls_raw_extension_t unknown_extensions[MAX_UNKNOWN_EXTENSIONS + 1];
+ unsigned status_request : 1;
+};
+
+struct st_ptls_server_hello_t {
+ uint8_t random_[PTLS_HELLO_RANDOM_SIZE];
+ ptls_iovec_t legacy_session_id;
+ int is_retry_request;
+ union {
+ ptls_iovec_t peerkey;
+ struct {
+ uint16_t selected_group;
+ ptls_iovec_t cookie;
+ } retry_request;
+ };
+};
+
+struct st_ptls_key_schedule_t {
+ unsigned generation; /* early secret (1), hanshake secret (2), master secret (3) */
+ uint8_t secret[PTLS_MAX_DIGEST_SIZE];
+ size_t num_hashes;
+ struct {
+ ptls_hash_algorithm_t *algo;
+ ptls_hash_context_t *ctx;
+ } hashes[1];
+};
+
+struct st_ptls_extension_decoder_t {
+ uint16_t type;
+ int (*cb)(ptls_t *tls, void *arg, const uint8_t *src, const uint8_t *const end);
+};
+
+struct st_ptls_extension_bitmap_t {
+ uint8_t bits[8]; /* only ids below 64 is tracked */
+};
+
+static uint8_t zeroes_of_max_digest_size[PTLS_MAX_DIGEST_SIZE] = {0};
+
+static int is_supported_version(uint16_t v)
+{
+ size_t i;
+ for (i = 0; i != sizeof(supported_versions) / sizeof(supported_versions[0]); ++i)
+ if (supported_versions[i] == v)
+ return 1;
+ return 0;
+}
+
+static inline int extension_bitmap_is_set(struct st_ptls_extension_bitmap_t *bitmap, uint16_t id)
+{
+ if (id < sizeof(bitmap->bits) * 8)
+ return (bitmap->bits[id / 8] & (1 << (id % 8))) != 0;
+ return 0;
+}
+
+static inline void extension_bitmap_set(struct st_ptls_extension_bitmap_t *bitmap, uint16_t id)
+{
+ if (id < sizeof(bitmap->bits) * 8)
+ bitmap->bits[id / 8] |= 1 << (id % 8);
+}
+
+static inline void init_extension_bitmap(struct st_ptls_extension_bitmap_t *bitmap, uint8_t hstype)
+{
+ *bitmap = (struct st_ptls_extension_bitmap_t){{0}};
+
+#define EXT(extid, proc) \
+ do { \
+ int _found = 0; \
+ do { \
+ proc \
+ } while (0); \
+ if (!_found) \
+ extension_bitmap_set(bitmap, PTLS_EXTENSION_TYPE_##extid); \
+ } while (0)
+#define ALLOW(allowed_hstype) _found = _found || hstype == PTLS_HANDSHAKE_TYPE_##allowed_hstype
+
+ /* Implements the table found in section 4.2 of draft-19; "If an implementation receives an extension which it recognizes and
+ * which is not specified for the message in which it appears it MUST abort the handshake with an “illegal_parameter” alert."
+ */
+ EXT(SERVER_NAME, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(ENCRYPTED_EXTENSIONS);
+ });
+ EXT(STATUS_REQUEST, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(CERTIFICATE);
+ });
+ EXT(SUPPORTED_GROUPS, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(ENCRYPTED_EXTENSIONS);
+ });
+ EXT(SIGNATURE_ALGORITHMS, { ALLOW(CLIENT_HELLO); });
+ EXT(ALPN, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(ENCRYPTED_EXTENSIONS);
+ });
+ EXT(KEY_SHARE, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(SERVER_HELLO);
+ });
+ EXT(PRE_SHARED_KEY, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(SERVER_HELLO);
+ });
+ EXT(PSK_KEY_EXCHANGE_MODES, { ALLOW(CLIENT_HELLO); });
+ EXT(EARLY_DATA, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(ENCRYPTED_EXTENSIONS);
+ ALLOW(NEW_SESSION_TICKET);
+ });
+ EXT(COOKIE, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(SERVER_HELLO);
+ });
+ EXT(SUPPORTED_VERSIONS, {
+ ALLOW(CLIENT_HELLO);
+ ALLOW(SERVER_HELLO);
+ });
+
+#undef ALLOW
+#undef EXT
+}
+
+static uint16_t ntoh16(const uint8_t *src)
+{
+ return (uint16_t)src[0] << 8 | src[1];
+}
+
+static uint32_t ntoh24(const uint8_t *src)
+{
+ return (uint32_t)src[0] << 16 | (uint32_t)src[1] << 8 | src[2];
+}
+
+static uint32_t ntoh32(const uint8_t *src)
+{
+ return (uint32_t)src[0] << 24 | (uint32_t)src[1] << 16 | (uint32_t)src[2] << 8 | src[3];
+}
+
+static uint64_t ntoh64(const uint8_t *src)
+{
+ return (uint64_t)src[0] << 56 | (uint64_t)src[1] << 48 | (uint64_t)src[2] << 40 | (uint64_t)src[3] << 32 |
+ (uint64_t)src[4] << 24 | (uint64_t)src[5] << 16 | (uint64_t)src[6] << 8 | src[7];
+}
+
+void ptls_buffer__release_memory(ptls_buffer_t *buf)
+{
+ ptls_clear_memory(buf->base, buf->off);
+ if (buf->is_allocated)
+ free(buf->base);
+}
+
+int ptls_buffer_reserve(ptls_buffer_t *buf, size_t delta)
+{
+ if (buf->base == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+
+ if (PTLS_MEMORY_DEBUG || buf->capacity < buf->off + delta) {
+ uint8_t *newp;
+ size_t new_capacity = buf->capacity;
+ if (new_capacity < 1024)
+ new_capacity = 1024;
+ while (new_capacity < buf->off + delta) {
+ new_capacity *= 2;
+ }
+ if ((newp = malloc(new_capacity)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ memcpy(newp, buf->base, buf->off);
+ ptls_buffer__release_memory(buf);
+ buf->base = newp;
+ buf->capacity = new_capacity;
+ buf->is_allocated = 1;
+ }
+
+ return 0;
+}
+
+int ptls_buffer__do_pushv(ptls_buffer_t *buf, const void *src, size_t len)
+{
+ int ret;
+
+ if (len == 0)
+ return 0;
+ if ((ret = ptls_buffer_reserve(buf, len)) != 0)
+ return ret;
+ memcpy(buf->base + buf->off, src, len);
+ buf->off += len;
+ return 0;
+}
+
+int ptls_buffer__adjust_asn1_blocksize(ptls_buffer_t *buf, size_t body_size)
+{
+ fprintf(stderr, "unimplemented\n");
+ abort();
+}
+
+int ptls_buffer_push_asn1_ubigint(ptls_buffer_t *buf, const void *bignum, size_t size)
+{
+ const uint8_t *p = bignum, *const end = p + size;
+ int ret;
+
+ /* skip zeroes */
+ for (; end - p >= 1; ++p)
+ if (*p != 0)
+ break;
+
+ /* emit */
+ ptls_buffer_push(buf, 2);
+ ptls_buffer_push_asn1_block(buf, {
+ if (*p >= 0x80)
+ ptls_buffer_push(buf, 0);
+ if (p != end) {
+ ptls_buffer_pushv(buf, p, end - p);
+ } else {
+ ptls_buffer_pushv(buf, "", 1);
+ }
+ });
+ ret = 0;
+
+Exit:
+ return ret;
+}
+
+static void build_aad(uint8_t aad[5], size_t reclen)
+{
+ aad[0] = PTLS_CONTENT_TYPE_APPDATA;
+ aad[1] = PTLS_RECORD_VERSION_MAJOR;
+ aad[2] = PTLS_RECORD_VERSION_MINOR;
+ aad[3] = (uint8_t)(reclen >> 8);
+ aad[4] = (uint8_t)reclen;
+}
+
+static size_t aead_encrypt(struct st_ptls_traffic_protection_t *ctx, void *output, const void *input, size_t inlen,
+ uint8_t content_type)
+{
+ uint8_t aad[5];
+ size_t off = 0;
+
+ build_aad(aad, inlen + 1 + ctx->aead->algo->tag_size);
+ ptls_aead_encrypt_init(ctx->aead, ctx->seq++, aad, sizeof(aad));
+ off += ptls_aead_encrypt_update(ctx->aead, ((uint8_t *)output) + off, input, inlen);
+ off += ptls_aead_encrypt_update(ctx->aead, ((uint8_t *)output) + off, &content_type, 1);
+ off += ptls_aead_encrypt_final(ctx->aead, ((uint8_t *)output) + off);
+
+ return off;
+}
+
+static int aead_decrypt(struct st_ptls_traffic_protection_t *ctx, void *output, size_t *outlen, const void *input, size_t inlen)
+{
+ uint8_t aad[5];
+
+ build_aad(aad, inlen);
+ if ((*outlen = ptls_aead_decrypt(ctx->aead, output, input, inlen, ctx->seq, aad, sizeof(aad))) == SIZE_MAX)
+ return PTLS_ALERT_BAD_RECORD_MAC;
+ ++ctx->seq;
+ return 0;
+}
+
+#define buffer_push_record(buf, type, block) \
+ do { \
+ ptls_buffer_push((buf), (type), PTLS_RECORD_VERSION_MAJOR, PTLS_RECORD_VERSION_MINOR); \
+ ptls_buffer_push_block((buf), 2, block); \
+ } while (0)
+
+static int buffer_push_encrypted_records(ptls_buffer_t *buf, uint8_t type, const uint8_t *src, size_t len,
+ struct st_ptls_traffic_protection_t *enc)
+{
+ int ret = 0;
+
+ while (len != 0) {
+ size_t chunk_size = len;
+ if (chunk_size > PTLS_MAX_PLAINTEXT_RECORD_SIZE)
+ chunk_size = PTLS_MAX_PLAINTEXT_RECORD_SIZE;
+ buffer_push_record(buf, PTLS_CONTENT_TYPE_APPDATA, {
+ if ((ret = ptls_buffer_reserve(buf, chunk_size + enc->aead->algo->tag_size + 1)) != 0)
+ goto Exit;
+ buf->off += aead_encrypt(enc, buf->base + buf->off, src, chunk_size, type);
+ });
+ src += chunk_size;
+ len -= chunk_size;
+ }
+
+Exit:
+ return ret;
+}
+
+static int buffer_encrypt_record(ptls_buffer_t *buf, size_t rec_start, struct st_ptls_traffic_protection_t *enc)
+{
+ size_t bodylen = buf->off - rec_start - 5;
+ uint8_t *tmpbuf, type = buf->base[rec_start];
+ int ret;
+
+ /* fast path: do in-place encryption if only one record needs to be emitted */
+ if (bodylen <= PTLS_MAX_PLAINTEXT_RECORD_SIZE) {
+ size_t overhead = 1 + enc->aead->algo->tag_size;
+ if ((ret = ptls_buffer_reserve(buf, overhead)) != 0)
+ return ret;
+ size_t encrypted_len = aead_encrypt(enc, buf->base + rec_start + 5, buf->base + rec_start + 5, bodylen, type);
+ assert(encrypted_len == bodylen + overhead);
+ buf->off += overhead;
+ buf->base[rec_start] = PTLS_CONTENT_TYPE_APPDATA;
+ buf->base[rec_start + 3] = (encrypted_len >> 8) & 0xff;
+ buf->base[rec_start + 4] = encrypted_len & 0xff;
+ return 0;
+ }
+
+ /* move plaintext to temporary buffer */
+ if ((tmpbuf = malloc(bodylen)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ memcpy(tmpbuf, buf->base + rec_start + 5, bodylen);
+ ptls_clear_memory(buf->base + rec_start, bodylen + 5);
+ buf->off = rec_start;
+
+ /* push encrypted records */
+ ret = buffer_push_encrypted_records(buf, type, tmpbuf, bodylen, enc);
+
+Exit:
+ if (tmpbuf != NULL) {
+ ptls_clear_memory(tmpbuf, bodylen);
+ free(tmpbuf);
+ }
+ return ret;
+}
+
+#define buffer_push_handshake_body(buf, key_sched, type, block) \
+ do { \
+ size_t mess_start = (buf)->off; \
+ ptls_buffer_push((buf), (type)); \
+ ptls_buffer_push_block((buf), 3, { \
+ do { \
+ block \
+ } while (0); \
+ }); \
+ if ((key_sched) != NULL) \
+ key_schedule_update_hash((key_sched), (buf)->base + (mess_start), (buf)->off - (mess_start)); \
+ } while (0)
+
+#define buffer_push_handshake(buf, key_sched, enc, type, block) \
+ do { \
+ size_t rec_start = (buf)->off; \
+ buffer_push_record((buf), PTLS_CONTENT_TYPE_HANDSHAKE, \
+ { buffer_push_handshake_body((buf), (key_sched), (type), block); }); \
+ if ((enc) != NULL) { \
+ if ((ret = buffer_encrypt_record((buf), rec_start, (enc))) != 0) \
+ goto Exit; \
+ } \
+ } while (0)
+
+#define buffer_push_extension(buf, type, block) \
+ do { \
+ ptls_buffer_push16((buf), (type)); \
+ ptls_buffer_push_block((buf), 2, block); \
+ } while (0);
+
+#define decode_open_extensions(src, end, hstype, exttype, block) \
+ do { \
+ struct st_ptls_extension_bitmap_t bitmap; \
+ init_extension_bitmap(&bitmap, (hstype)); \
+ ptls_decode_open_block((src), end, 2, { \
+ while ((src) != end) { \
+ if ((ret = ptls_decode16((exttype), &(src), end)) != 0) \
+ goto Exit; \
+ if (extension_bitmap_is_set(&bitmap, *(exttype)) != 0) { \
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER; \
+ goto Exit; \
+ } \
+ extension_bitmap_set(&bitmap, *(exttype)); \
+ ptls_decode_open_block((src), end, 2, block); \
+ } \
+ }); \
+ } while (0)
+
+#define decode_extensions(src, end, hstype, exttype, block) \
+ do { \
+ decode_open_extensions((src), end, hstype, exttype, block); \
+ ptls_decode_assert_block_close((src), end); \
+ } while (0)
+
+int ptls_decode16(uint16_t *value, const uint8_t **src, const uint8_t *end)
+{
+ if (end - *src < 2)
+ return PTLS_ALERT_DECODE_ERROR;
+ *value = ntoh16(*src);
+ *src += 2;
+ return 0;
+}
+
+int ptls_decode32(uint32_t *value, const uint8_t **src, const uint8_t *end)
+{
+ if (end - *src < 4)
+ return PTLS_ALERT_DECODE_ERROR;
+ *value = ntoh32(*src);
+ *src += 4;
+ return 0;
+}
+
+int ptls_decode64(uint64_t *value, const uint8_t **src, const uint8_t *end)
+{
+ if (end - *src < 8)
+ return PTLS_ALERT_DECODE_ERROR;
+ *value = ntoh64(*src);
+ *src += 8;
+ return 0;
+}
+
+static void key_schedule_free(struct st_ptls_key_schedule_t *sched)
+{
+ size_t i;
+ ptls_clear_memory(sched->secret, sizeof(sched->secret));
+ for (i = 0; i != sched->num_hashes; ++i)
+ sched->hashes[i].ctx->final(sched->hashes[i].ctx, NULL, PTLS_HASH_FINAL_MODE_FREE);
+ free(sched);
+}
+
+static struct st_ptls_key_schedule_t *key_schedule_new(ptls_cipher_suite_t *preferred, ptls_cipher_suite_t **offered)
+{
+#define FOREACH_HASH(block) \
+ do { \
+ ptls_cipher_suite_t *cs; \
+ if ((cs = preferred) != NULL) { \
+ block \
+ } \
+ if (offered != NULL) { \
+ size_t i, j; \
+ for (i = 0; (cs = offered[i]) != NULL; ++i) { \
+ if (preferred == NULL || cs->hash != preferred->hash) { \
+ for (j = 0; j != i; ++j) \
+ if (cs->hash == offered[j]->hash) \
+ break; \
+ if (j == i) { \
+ block \
+ } \
+ } \
+ } \
+ } \
+ } while (0)
+
+ struct st_ptls_key_schedule_t *sched;
+
+ { /* allocate */
+ size_t num_hashes = 0;
+ FOREACH_HASH({ ++num_hashes; });
+ if ((sched = malloc(offsetof(struct st_ptls_key_schedule_t, hashes) + sizeof(sched->hashes[0]) * num_hashes)) == NULL)
+ return NULL;
+ *sched = (struct st_ptls_key_schedule_t){0};
+ }
+
+ /* setup the hash algos and contexts */
+ FOREACH_HASH({
+ sched->hashes[sched->num_hashes].algo = cs->hash;
+ if ((sched->hashes[sched->num_hashes].ctx = cs->hash->create()) == NULL)
+ goto Fail;
+ ++sched->num_hashes;
+ });
+
+ return sched;
+Fail:
+ key_schedule_free(sched);
+ return NULL;
+
+#undef FOREACH_HASH
+}
+
+static int key_schedule_extract(struct st_ptls_key_schedule_t *sched, ptls_iovec_t ikm)
+{
+ int ret;
+
+ if (ikm.base == NULL)
+ ikm = ptls_iovec_init(zeroes_of_max_digest_size, sched->hashes[0].algo->digest_size);
+
+ if (sched->generation != 0 &&
+ (ret = ptls_hkdf_expand_label(sched->hashes[0].algo, sched->secret, sched->hashes[0].algo->digest_size,
+ ptls_iovec_init(sched->secret, sched->hashes[0].algo->digest_size), "derived",
+ ptls_iovec_init(sched->hashes[0].algo->empty_digest, sched->hashes[0].algo->digest_size),
+ NULL)) != 0)
+ return ret;
+
+ ++sched->generation;
+ ret = ptls_hkdf_extract(sched->hashes[0].algo, sched->secret,
+ ptls_iovec_init(sched->secret, sched->hashes[0].algo->digest_size), ikm);
+ PTLS_DEBUGF("%s: %u, %02x%02x\n", __FUNCTION__, sched->generation, (int)sched->secret[0], (int)sched->secret[1]);
+ return ret;
+}
+
+static int key_schedule_select_one(struct st_ptls_key_schedule_t *sched, ptls_cipher_suite_t *cs, int reset)
+{
+ size_t found_slot = SIZE_MAX, i;
+ int ret;
+
+ assert(sched->generation == 1);
+
+ /* find the one, while freeing others */
+ for (i = 0; i != sched->num_hashes; ++i) {
+ if (sched->hashes[i].algo == cs->hash) {
+ assert(found_slot == SIZE_MAX);
+ found_slot = i;
+ } else {
+ sched->hashes[i].ctx->final(sched->hashes[i].ctx, NULL, PTLS_HASH_FINAL_MODE_FREE);
+ }
+ }
+ if (found_slot != 0) {
+ sched->hashes[0] = sched->hashes[found_slot];
+ reset = 1;
+ }
+ sched->num_hashes = 1;
+
+ /* recalculate the hash if a different hash as been selected than the one we used for calculating the early secrets */
+ if (reset) {
+ --sched->generation;
+ memset(sched->secret, 0, sizeof(sched->secret));
+ if ((ret = key_schedule_extract(sched, ptls_iovec_init(NULL, 0))) != 0)
+ goto Exit;
+ }
+
+ ret = 0;
+Exit:
+ return ret;
+}
+
+static void key_schedule_update_hash(struct st_ptls_key_schedule_t *sched, const uint8_t *msg, size_t msglen)
+{
+ size_t i;
+
+ PTLS_DEBUGF("%s:%zu\n", __FUNCTION__, msglen);
+ for (i = 0; i != sched->num_hashes; ++i)
+ sched->hashes[i].ctx->update(sched->hashes[i].ctx, msg, msglen);
+}
+
+static void key_schedule_update_ch1hash_prefix(struct st_ptls_key_schedule_t *sched)
+{
+ uint8_t prefix[4] = {PTLS_HANDSHAKE_TYPE_MESSAGE_HASH, 0, 0, (uint8_t)sched->hashes[0].algo->digest_size};
+ key_schedule_update_hash(sched, prefix, sizeof(prefix));
+}
+
+static void key_schedule_extract_ch1hash(struct st_ptls_key_schedule_t *sched, uint8_t *hash)
+{
+ sched->hashes[0].ctx->final(sched->hashes[0].ctx, hash, PTLS_HASH_FINAL_MODE_RESET);
+}
+
+static void key_schedule_transform_post_ch1hash(struct st_ptls_key_schedule_t *sched)
+{
+ uint8_t ch1hash[PTLS_MAX_DIGEST_SIZE];
+
+ key_schedule_extract_ch1hash(sched, ch1hash);
+
+ key_schedule_update_ch1hash_prefix(sched);
+ key_schedule_update_hash(sched, ch1hash, sched->hashes[0].algo->digest_size);
+}
+
+static int derive_secret_with_hash(struct st_ptls_key_schedule_t *sched, void *secret, const char *label, const uint8_t *hash)
+{
+ int ret = ptls_hkdf_expand_label(sched->hashes[0].algo, secret, sched->hashes[0].algo->digest_size,
+ ptls_iovec_init(sched->secret, sched->hashes[0].algo->digest_size), label,
+ ptls_iovec_init(hash, sched->hashes[0].algo->digest_size), NULL);
+ PTLS_DEBUGF("%s: (label=%s, hash=%02x%02x) => %02x%02x\n", __FUNCTION__, label, hash[0], hash[1], ((uint8_t *)secret)[0],
+ ((uint8_t *)secret)[1]);
+ return ret;
+}
+
+static int derive_secret(struct st_ptls_key_schedule_t *sched, void *secret, const char *label)
+{
+ uint8_t hash_value[PTLS_MAX_DIGEST_SIZE];
+
+ sched->hashes[0].ctx->final(sched->hashes[0].ctx, hash_value, PTLS_HASH_FINAL_MODE_SNAPSHOT);
+ int ret = derive_secret_with_hash(sched, secret, label, hash_value);
+ ptls_clear_memory(hash_value, sizeof(hash_value));
+ return ret;
+}
+
+static int derive_secret_with_empty_digest(struct st_ptls_key_schedule_t *sched, void *secret, const char *label)
+{
+ return derive_secret_with_hash(sched, secret, label, sched->hashes[0].algo->empty_digest);
+}
+
+static int derive_exporter_secret(ptls_t *tls, int is_early)
+{
+ if (tls->ctx->use_exporter)
+ return 0;
+
+ uint8_t **slot = is_early ? &tls->exporter_master_secret.early : &tls->exporter_master_secret.one_rtt;
+ assert(*slot == NULL);
+ if ((*slot = malloc(tls->key_schedule->hashes[0].algo->digest_size)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ return derive_secret(tls->key_schedule, *slot, is_early ? "e exp master" : "exp master");
+}
+
+static void free_exporter_master_secret(ptls_t *tls, int is_early)
+{
+ uint8_t *slot = is_early ? tls->exporter_master_secret.early : tls->exporter_master_secret.one_rtt;
+ if (slot == NULL)
+ return;
+ assert(tls->key_schedule != NULL);
+ ptls_clear_memory(slot, tls->key_schedule->hashes[0].algo->digest_size);
+ free(slot);
+}
+
+static int derive_resumption_secret(struct st_ptls_key_schedule_t *sched, uint8_t *secret, ptls_iovec_t nonce)
+{
+ int ret;
+
+ if ((ret = derive_secret(sched, secret, "res master")) != 0)
+ goto Exit;
+ if ((ret = ptls_hkdf_expand_label(sched->hashes[0].algo, secret, sched->hashes[0].algo->digest_size,
+ ptls_iovec_init(secret, sched->hashes[0].algo->digest_size), "resumption", nonce, NULL)) != 0)
+ goto Exit;
+
+Exit:
+ if (ret != 0)
+ ptls_clear_memory(secret, sched->hashes[0].algo->digest_size);
+ return ret;
+}
+
+static int decode_new_session_ticket(uint32_t *lifetime, uint32_t *age_add, ptls_iovec_t *nonce, ptls_iovec_t *ticket,
+ uint32_t *max_early_data_size, const uint8_t *src, const uint8_t *const end)
+{
+ uint16_t exttype;
+ int ret;
+
+ if ((ret = ptls_decode32(lifetime, &src, end)) != 0)
+ goto Exit;
+ if ((ret = ptls_decode32(age_add, &src, end)) != 0)
+ goto Exit;
+ ptls_decode_open_block(src, end, 1, {
+ *nonce = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ ptls_decode_open_block(src, end, 2, {
+ if (src == end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ *ticket = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+
+ *max_early_data_size = 0;
+ decode_extensions(src, end, PTLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET, &exttype, {
+ switch (exttype) {
+ case PTLS_EXTENSION_TYPE_EARLY_DATA:
+ if ((ret = ptls_decode32(max_early_data_size, &src, end)) != 0)
+ goto Exit;
+ break;
+ default:
+ src = end;
+ break;
+ }
+ });
+
+ ret = 0;
+Exit:
+ return ret;
+}
+
+static int decode_stored_session_ticket(ptls_context_t *ctx, ptls_key_exchange_algorithm_t **key_share, ptls_cipher_suite_t **cs,
+ ptls_iovec_t *secret, uint32_t *obfuscated_ticket_age, ptls_iovec_t *ticket,
+ uint32_t *max_early_data_size, const uint8_t *src, const uint8_t *const end)
+{
+ uint16_t kxid, csid;
+ uint32_t lifetime, age_add;
+ uint64_t obtained_at, now;
+ ptls_iovec_t nonce;
+ int ret;
+
+ /* decode */
+ if ((ret = ptls_decode64(&obtained_at, &src, end)) != 0)
+ goto Exit;
+ if ((ret = ptls_decode16(&kxid, &src, end)) != 0)
+ goto Exit;
+ if ((ret = ptls_decode16(&csid, &src, end)) != 0)
+ goto Exit;
+ ptls_decode_open_block(src, end, 3, {
+ if ((ret = decode_new_session_ticket(&lifetime, &age_add, &nonce, ticket, max_early_data_size, src, end)) != 0)
+ goto Exit;
+ src = end;
+ });
+ ptls_decode_block(src, end, 2, {
+ *secret = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+
+ { /* determine the key-exchange */
+ ptls_key_exchange_algorithm_t **cand;
+ for (cand = ctx->key_exchanges; *cand != NULL; ++cand)
+ if ((*cand)->id == kxid)
+ break;
+ if (*cand == NULL) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ *key_share = *cand;
+ }
+
+ { /* determine the cipher-suite */
+ ptls_cipher_suite_t **cand;
+ for (cand = ctx->cipher_suites; *cand != NULL; ++cand)
+ if ((*cand)->id == csid)
+ break;
+ if (*cand == NULL) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ *cs = *cand;
+ }
+
+ /* calculate obfuscated_ticket_age */
+ now = ctx->get_time->cb(ctx->get_time);
+ if (!(obtained_at <= now && now - obtained_at < 7 * 86400 * 1000)) {
+ ret = PTLS_ERROR_LIBRARY;
+ goto Exit;
+ }
+ *obfuscated_ticket_age = (uint32_t)(now - obtained_at) + age_add;
+
+ ret = 0;
+Exit:
+ return ret;
+}
+
+static int get_traffic_key(ptls_hash_algorithm_t *algo, void *key, size_t key_size, int is_iv, const void *secret,
+ const char *base_label)
+{
+ return ptls_hkdf_expand_label(algo, key, key_size, ptls_iovec_init(secret, algo->digest_size), is_iv ? "iv" : "key",
+ ptls_iovec_init(NULL, 0), base_label);
+}
+
+static int setup_traffic_protection(ptls_t *tls, int is_enc, const char *secret_label, const char *log_label)
+{
+ struct st_ptls_traffic_protection_t *ctx = is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec;
+
+ if (secret_label != NULL) {
+ int ret;
+ if ((ret = derive_secret(tls->key_schedule, ctx->secret, secret_label)) != 0)
+ return ret;
+ }
+
+ if (ctx->aead != NULL)
+ ptls_aead_free(ctx->aead);
+ if ((ctx->aead = ptls_aead_new(tls->cipher_suite->aead, tls->cipher_suite->hash, is_enc, ctx->secret, NULL)) == NULL)
+ return PTLS_ERROR_NO_MEMORY; /* TODO obtain error from ptls_aead_new */
+ ctx->seq = 0;
+
+ if (tls->ctx->log_secret != NULL)
+ tls->ctx->log_secret->cb(tls->ctx->log_secret, tls, log_label,
+ ptls_iovec_init(ctx->secret, tls->key_schedule->hashes[0].algo->digest_size));
+ PTLS_DEBUGF("[%s] %02x%02x,%02x%02x\n", log_label, (unsigned)ctx->secret[0], (unsigned)ctx->secret[1],
+ (unsigned)ctx->aead->static_iv[0], (unsigned)ctx->aead->static_iv[1]);
+
+ return 0;
+}
+
+static int retire_early_data_secret(ptls_t *tls, int is_enc)
+{
+ assert(tls->early_data != NULL);
+ memcpy((is_enc ? &tls->traffic_protection.enc : &tls->traffic_protection.dec)->secret, tls->early_data->next_secret,
+ PTLS_MAX_DIGEST_SIZE);
+ ptls_clear_memory(tls->early_data, sizeof(*tls->early_data));
+ free(tls->early_data);
+ tls->early_data = NULL;
+
+ return setup_traffic_protection(tls, is_enc, NULL, "CLIENT_HANDSHAKE_TRAFFIC_SECRET");
+}
+
+#define SESSION_IDENTIFIER_MAGIC "ptls0001" /* the number should be changed upon incompatible format change */
+#define SESSION_IDENTIFIER_MAGIC_SIZE (sizeof(SESSION_IDENTIFIER_MAGIC) - 1)
+
+static int encode_session_identifier(ptls_context_t *ctx, ptls_buffer_t *buf, uint32_t ticket_age_add, ptls_iovec_t ticket_nonce,
+ struct st_ptls_key_schedule_t *sched, const char *server_name, uint16_t key_exchange_id,
+ uint16_t csid, const char *negotiated_protocol)
+{
+ int ret = 0;
+
+ ptls_buffer_push_block(buf, 2, {
+ /* format id */
+ ptls_buffer_pushv(buf, SESSION_IDENTIFIER_MAGIC, SESSION_IDENTIFIER_MAGIC_SIZE);
+ /* date */
+ ptls_buffer_push64(buf, ctx->get_time->cb(ctx->get_time));
+ /* resumption master secret */
+ ptls_buffer_push_block(buf, 2, {
+ if ((ret = ptls_buffer_reserve(buf, sched->hashes[0].algo->digest_size)) != 0)
+ goto Exit;
+ if ((ret = derive_resumption_secret(sched, buf->base + buf->off, ticket_nonce)) != 0)
+ goto Exit;
+ buf->off += sched->hashes[0].algo->digest_size;
+ });
+ /* key-exchange */
+ ptls_buffer_push16(buf, key_exchange_id);
+ /* cipher-suite */
+ ptls_buffer_push16(buf, csid);
+ /* ticket_age_add */
+ ptls_buffer_push32(buf, ticket_age_add);
+ /* server-name */
+ ptls_buffer_push_block(buf, 2, {
+ if (server_name != NULL)
+ ptls_buffer_pushv(buf, server_name, strlen(server_name));
+ });
+ /* alpn */
+ ptls_buffer_push_block(buf, 1, {
+ if (negotiated_protocol != NULL)
+ ptls_buffer_pushv(buf, negotiated_protocol, strlen(negotiated_protocol));
+ });
+ });
+
+Exit:
+ return ret;
+}
+
+int decode_session_identifier(uint64_t *issued_at, ptls_iovec_t *psk, uint32_t *ticket_age_add, ptls_iovec_t *server_name,
+ uint16_t *key_exchange_id, uint16_t *csid, ptls_iovec_t *negotiated_protocol, const uint8_t *src,
+ const uint8_t *const end)
+{
+ int ret = 0;
+
+ ptls_decode_block(src, end, 2, {
+ if (end - src < SESSION_IDENTIFIER_MAGIC_SIZE ||
+ memcmp(src, SESSION_IDENTIFIER_MAGIC, SESSION_IDENTIFIER_MAGIC_SIZE) != 0) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ src += SESSION_IDENTIFIER_MAGIC_SIZE;
+ if ((ret = ptls_decode64(issued_at, &src, end)) != 0)
+ goto Exit;
+ ptls_decode_open_block(src, end, 2, {
+ *psk = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ if ((ret = ptls_decode16(key_exchange_id, &src, end)) != 0)
+ goto Exit;
+ if ((ret = ptls_decode16(csid, &src, end)) != 0)
+ goto Exit;
+ if ((ret = ptls_decode32(ticket_age_add, &src, end)) != 0)
+ goto Exit;
+ ptls_decode_open_block(src, end, 2, {
+ *server_name = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ ptls_decode_open_block(src, end, 1, {
+ *negotiated_protocol = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ });
+
+Exit:
+ return ret;
+}
+
+static size_t build_certificate_verify_signdata(uint8_t *data, struct st_ptls_key_schedule_t *sched, const char *context_string)
+{
+ size_t datalen = 0;
+
+ memset(data + datalen, 32, 64);
+ datalen += 64;
+ memcpy(data + datalen, context_string, strlen(context_string) + 1);
+ datalen += strlen(context_string) + 1;
+ sched->hashes[0].ctx->final(sched->hashes[0].ctx, data + datalen, PTLS_HASH_FINAL_MODE_SNAPSHOT);
+ datalen += sched->hashes[0].algo->digest_size;
+ assert(datalen <= PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE);
+
+ return datalen;
+}
+
+static int calc_verify_data(void *output, struct st_ptls_key_schedule_t *sched, const void *secret)
+{
+ ptls_hash_context_t *hmac;
+ uint8_t digest[PTLS_MAX_DIGEST_SIZE];
+ int ret;
+
+ if ((ret = ptls_hkdf_expand_label(sched->hashes[0].algo, digest, sched->hashes[0].algo->digest_size,
+ ptls_iovec_init(secret, sched->hashes[0].algo->digest_size), "finished",
+ ptls_iovec_init(NULL, 0), NULL)) != 0)
+ return ret;
+ if ((hmac = ptls_hmac_create(sched->hashes[0].algo, digest, sched->hashes[0].algo->digest_size)) == NULL) {
+ ptls_clear_memory(digest, sizeof(digest));
+ return PTLS_ERROR_NO_MEMORY;
+ }
+
+ sched->hashes[0].ctx->final(sched->hashes[0].ctx, digest, PTLS_HASH_FINAL_MODE_SNAPSHOT);
+ PTLS_DEBUGF("%s: %02x%02x,%02x%02x\n", __FUNCTION__, ((uint8_t *)secret)[0], ((uint8_t *)secret)[1], digest[0], digest[1]);
+ hmac->update(hmac, digest, sched->hashes[0].algo->digest_size);
+ ptls_clear_memory(digest, sizeof(digest));
+ hmac->final(hmac, output, PTLS_HASH_FINAL_MODE_FREE);
+
+ return 0;
+}
+
+static int verify_finished(ptls_t *tls, ptls_iovec_t message)
+{
+ uint8_t verify_data[PTLS_MAX_DIGEST_SIZE];
+ int ret;
+
+ if (PTLS_HANDSHAKE_HEADER_SIZE + tls->key_schedule->hashes[0].algo->digest_size != message.len) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+
+ if ((ret = calc_verify_data(verify_data, tls->key_schedule, tls->traffic_protection.dec.secret)) != 0)
+ goto Exit;
+ if (memcmp(message.base + PTLS_HANDSHAKE_HEADER_SIZE, verify_data, tls->key_schedule->hashes[0].algo->digest_size) != 0) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+
+Exit:
+ ptls_clear_memory(verify_data, sizeof(verify_data));
+ return ret;
+}
+
+static int send_finished(ptls_t *tls, ptls_buffer_t *sendbuf)
+{
+ int ret;
+
+ buffer_push_handshake(sendbuf, tls->key_schedule, &tls->traffic_protection.enc, PTLS_HANDSHAKE_TYPE_FINISHED, {
+ if ((ret = ptls_buffer_reserve(sendbuf, tls->key_schedule->hashes[0].algo->digest_size)) != 0)
+ goto Exit;
+ if ((ret = calc_verify_data(sendbuf->base + sendbuf->off, tls->key_schedule, tls->traffic_protection.enc.secret)) != 0)
+ goto Exit;
+ sendbuf->off += tls->key_schedule->hashes[0].algo->digest_size;
+ });
+
+Exit:
+ return ret;
+}
+
+static int send_session_ticket(ptls_t *tls, ptls_buffer_t *sendbuf)
+{
+ ptls_hash_context_t *msghash_backup = tls->key_schedule->hashes[0].ctx->clone_(tls->key_schedule->hashes[0].ctx);
+ ptls_buffer_t session_id;
+ char session_id_smallbuf[128];
+ uint32_t ticket_age_add;
+ int ret = 0;
+
+ assert(tls->ctx->ticket_lifetime != 0);
+ assert(tls->ctx->encrypt_ticket != NULL);
+
+ { /* calculate verify-data that will be sent by the client */
+ size_t orig_off = sendbuf->off;
+ if (tls->early_data != NULL) {
+ assert(tls->state == PTLS_STATE_SERVER_EXPECT_END_OF_EARLY_DATA);
+ buffer_push_handshake_body(sendbuf, tls->key_schedule, PTLS_HANDSHAKE_TYPE_END_OF_EARLY_DATA, {});
+ sendbuf->off = orig_off;
+ }
+ buffer_push_handshake_body(sendbuf, tls->key_schedule, PTLS_HANDSHAKE_TYPE_FINISHED, {
+ if ((ret = ptls_buffer_reserve(sendbuf, tls->key_schedule->hashes[0].algo->digest_size)) != 0)
+ goto Exit;
+ if ((ret = calc_verify_data(sendbuf->base + sendbuf->off, tls->key_schedule,
+ tls->early_data != NULL ? tls->early_data->next_secret
+ : tls->traffic_protection.dec.secret)) != 0)
+ goto Exit;
+ sendbuf->off += tls->key_schedule->hashes[0].algo->digest_size;
+ });
+ sendbuf->off = orig_off;
+ }
+
+ tls->ctx->random_bytes(&ticket_age_add, sizeof(ticket_age_add));
+
+ /* build the raw nsk */
+ ptls_buffer_init(&session_id, session_id_smallbuf, sizeof(session_id_smallbuf));
+ ret = encode_session_identifier(tls->ctx, &session_id, ticket_age_add, ptls_iovec_init(NULL, 0), tls->key_schedule,
+ tls->server_name, tls->key_share->id, tls->cipher_suite->id, tls->negotiated_protocol);
+ if (ret != 0)
+ goto Exit;
+
+ /* encrypt and send */
+ buffer_push_handshake(sendbuf, tls->key_schedule, &tls->traffic_protection.enc, PTLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET, {
+ ptls_buffer_push32(sendbuf, tls->ctx->ticket_lifetime);
+ ptls_buffer_push32(sendbuf, ticket_age_add);
+ ptls_buffer_push_block(sendbuf, 1, {});
+ ptls_buffer_push_block(sendbuf, 2, {
+ if ((ret = tls->ctx->encrypt_ticket->cb(tls->ctx->encrypt_ticket, tls, 1, sendbuf,
+ ptls_iovec_init(session_id.base, session_id.off))) != 0)
+ goto Exit;
+ });
+ ptls_buffer_push_block(sendbuf, 2, {
+ if (tls->ctx->max_early_data_size != 0)
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_EARLY_DATA,
+ { ptls_buffer_push32(sendbuf, tls->ctx->max_early_data_size); });
+ });
+ });
+
+Exit:
+ ptls_buffer_dispose(&session_id);
+
+ /* restore handshake state */
+ tls->key_schedule->hashes[0].ctx->final(tls->key_schedule->hashes[0].ctx, NULL, PTLS_HASH_FINAL_MODE_FREE);
+ tls->key_schedule->hashes[0].ctx = msghash_backup;
+
+ return ret;
+}
+
+static int push_change_cipher_spec(ptls_t *tls, ptls_buffer_t *sendbuf)
+{
+ int ret = 0;
+
+ if (!tls->send_change_cipher_spec)
+ goto Exit;
+ buffer_push_record(sendbuf, PTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, { ptls_buffer_push(sendbuf, 1); });
+ tls->send_change_cipher_spec = 0;
+Exit:
+ return ret;
+}
+
+static int push_additional_extensions(ptls_handshake_properties_t *properties, ptls_buffer_t *sendbuf)
+{
+ int ret;
+
+ if (properties != NULL && properties->additional_extensions != NULL) {
+ ptls_raw_extension_t *ext;
+ for (ext = properties->additional_extensions; ext->type != UINT16_MAX; ++ext) {
+ buffer_push_extension(sendbuf, ext->type, { ptls_buffer_pushv(sendbuf, ext->data.base, ext->data.len); });
+ }
+ }
+ ret = 0;
+Exit:
+ return ret;
+}
+
+static int send_client_hello(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_handshake_properties_t *properties, ptls_iovec_t *cookie)
+{
+ ptls_iovec_t resumption_secret = {NULL}, resumption_ticket;
+ uint32_t obfuscated_ticket_age = 0;
+ size_t msghash_off;
+ uint8_t binder_key[PTLS_MAX_DIGEST_SIZE];
+ int ret, is_second_flight = tls->key_schedule != NULL;
+
+ if (properties != NULL) {
+ /* setup resumption-related data. If successful, resumption_secret becomes a non-zero value. */
+ if (properties->client.session_ticket.base != NULL) {
+ ptls_key_exchange_algorithm_t *key_share = NULL;
+ ptls_cipher_suite_t *cipher_suite = NULL;
+ uint32_t max_early_data_size;
+ if (decode_stored_session_ticket(tls->ctx, &key_share, &cipher_suite, &resumption_secret, &obfuscated_ticket_age,
+ &resumption_ticket, &max_early_data_size, properties->client.session_ticket.base,
+ properties->client.session_ticket.base + properties->client.session_ticket.len) == 0) {
+ tls->client.offered_psk = 1;
+ tls->key_share = key_share;
+ tls->cipher_suite = cipher_suite;
+ if (!is_second_flight && max_early_data_size != 0 && properties->client.max_early_data_size != NULL) {
+ *properties->client.max_early_data_size = max_early_data_size;
+ if ((tls->early_data = malloc(sizeof(*tls->early_data))) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ }
+ } else {
+ resumption_secret = ptls_iovec_init(NULL, 0);
+ }
+ }
+ if (properties->client.max_early_data_size != NULL && tls->early_data == NULL)
+ *properties->client.max_early_data_size = 0;
+ }
+
+ /* use the default key share if still not undetermined */
+ if (tls->key_share == NULL && !(properties != NULL && properties->client.negotiate_before_key_exchange))
+ tls->key_share = tls->ctx->key_exchanges[0];
+
+ if (!is_second_flight) {
+ tls->key_schedule = key_schedule_new(tls->cipher_suite, tls->ctx->cipher_suites);
+ if ((ret = key_schedule_extract(tls->key_schedule, resumption_secret)) != 0)
+ goto Exit;
+ }
+
+ msghash_off = sendbuf->off + 5;
+ buffer_push_handshake(sendbuf, NULL, NULL, PTLS_HANDSHAKE_TYPE_CLIENT_HELLO, {
+ /* legacy_version */
+ ptls_buffer_push16(sendbuf, 0x0303);
+ /* random_bytes */
+ ptls_buffer_pushv(sendbuf, tls->client_random, sizeof(tls->client_random));
+ /* lecagy_session_id */
+ ptls_buffer_push_block(
+ sendbuf, 1, { ptls_buffer_pushv(sendbuf, tls->client.legacy_session_id, sizeof(tls->client.legacy_session_id)); });
+ /* cipher_suites */
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_cipher_suite_t **cs = tls->ctx->cipher_suites;
+ for (; *cs != NULL; ++cs)
+ ptls_buffer_push16(sendbuf, (*cs)->id);
+ });
+ /* legacy_compression_methods */
+ ptls_buffer_push_block(sendbuf, 1, { ptls_buffer_push(sendbuf, 0); });
+ /* extensions */
+ ptls_buffer_push_block(sendbuf, 2, {
+ if (tls->server_name != NULL) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SERVER_NAME, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_buffer_push(sendbuf, PTLS_SERVER_NAME_TYPE_HOSTNAME);
+ ptls_buffer_push_block(sendbuf, 2,
+ { ptls_buffer_pushv(sendbuf, tls->server_name, strlen(tls->server_name)); });
+ });
+ });
+ }
+ if (properties != NULL && properties->client.negotiated_protocols.count != 0) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_ALPN, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ size_t i;
+ for (i = 0; i != properties->client.negotiated_protocols.count; ++i) {
+ ptls_buffer_push_block(sendbuf, 1, {
+ ptls_iovec_t p = properties->client.negotiated_protocols.list[i];
+ ptls_buffer_pushv(sendbuf, p.base, p.len);
+ });
+ }
+ });
+ });
+ }
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS, {
+ ptls_buffer_push_block(sendbuf, 1, {
+ size_t i;
+ for (i = 0; i != sizeof(supported_versions) / sizeof(supported_versions[0]); ++i)
+ ptls_buffer_push16(sendbuf, supported_versions[i]);
+ });
+ });
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256);
+ ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256);
+ ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PKCS1_SHA256);
+ ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PKCS1_SHA1);
+ });
+ });
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SUPPORTED_GROUPS, {
+ ptls_key_exchange_algorithm_t **algo = tls->ctx->key_exchanges;
+ ptls_buffer_push_block(sendbuf, 2, {
+ for (; *algo != NULL; ++algo)
+ ptls_buffer_push16(sendbuf, (*algo)->id);
+ });
+ });
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_KEY_SHARE, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ if (tls->key_share != NULL) {
+ ptls_iovec_t pubkey;
+ if ((ret = tls->key_share->create(&tls->client.key_share_ctx, &pubkey)) != 0)
+ goto Exit;
+ ptls_buffer_push16(sendbuf, tls->key_share->id);
+ ptls_buffer_push_block(sendbuf, 2, { ptls_buffer_pushv(sendbuf, pubkey.base, pubkey.len); });
+ }
+ });
+ });
+ if (cookie != NULL && cookie->base != NULL) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_COOKIE, {
+ ptls_buffer_push_block(sendbuf, 2, { ptls_buffer_pushv(sendbuf, cookie->base, cookie->len); });
+ });
+ }
+ if ((ret = push_additional_extensions(properties, sendbuf)) != 0)
+ goto Exit;
+ if (tls->ctx->save_ticket != NULL) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES, {
+ ptls_buffer_push_block(sendbuf, 1, {
+ if (!tls->ctx->require_dhe_on_psk)
+ ptls_buffer_push(sendbuf, PTLS_PSK_KE_MODE_PSK);
+ ptls_buffer_push(sendbuf, PTLS_PSK_KE_MODE_PSK_DHE);
+ });
+ });
+ if (resumption_secret.base != NULL) {
+ if (tls->early_data != NULL && !is_second_flight)
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_EARLY_DATA, {});
+ /* pre-shared key "MUST be the last extension in the ClientHello" (draft-17 section 4.2.6) */
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_PRE_SHARED_KEY, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_buffer_push_block(sendbuf, 2,
+ { ptls_buffer_pushv(sendbuf, resumption_ticket.base, resumption_ticket.len); });
+ ptls_buffer_push32(sendbuf, obfuscated_ticket_age);
+ });
+ /* allocate space for PSK binder. the space is filled at the bottom of the function */
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_buffer_push_block(sendbuf, 1, {
+ if ((ret = ptls_buffer_reserve(sendbuf, tls->key_schedule->hashes[0].algo->digest_size)) != 0)
+ goto Exit;
+ sendbuf->off += tls->key_schedule->hashes[0].algo->digest_size;
+ });
+ });
+ });
+ }
+ }
+ });
+ });
+
+ /* update the message hash, filling in the PSK binder HMAC if necessary */
+ if (resumption_secret.base != NULL) {
+ size_t psk_binder_off = sendbuf->off - (3 + tls->key_schedule->hashes[0].algo->digest_size);
+ if ((ret = derive_secret_with_empty_digest(tls->key_schedule, binder_key, "res binder")) != 0)
+ goto Exit;
+ key_schedule_update_hash(tls->key_schedule, sendbuf->base + msghash_off, psk_binder_off - msghash_off);
+ msghash_off = psk_binder_off;
+ if ((ret = calc_verify_data(sendbuf->base + psk_binder_off + 3, tls->key_schedule, binder_key)) != 0)
+ goto Exit;
+ }
+ key_schedule_update_hash(tls->key_schedule, sendbuf->base + msghash_off, sendbuf->off - msghash_off);
+
+ if (tls->early_data != NULL) {
+ if ((ret = setup_traffic_protection(tls, 1, "c e traffic", "CLIENT_EARLY_TRAFFIC_SECRET")) != 0)
+ goto Exit;
+ if ((ret = push_change_cipher_spec(tls, sendbuf)) != 0)
+ goto Exit;
+ }
+ if (resumption_secret.base != NULL && !is_second_flight) {
+ if ((ret = derive_exporter_secret(tls, 1)) != 0)
+ goto Exit;
+ }
+ tls->state = cookie == NULL ? PTLS_STATE_CLIENT_EXPECT_SERVER_HELLO : PTLS_STATE_CLIENT_EXPECT_SECOND_SERVER_HELLO;
+ ret = PTLS_ERROR_IN_PROGRESS;
+
+Exit:
+ ptls_clear_memory(binder_key, sizeof(binder_key));
+ return ret;
+}
+
+static int decode_key_share_entry(uint16_t *group, ptls_iovec_t *key_exchange, const uint8_t **src, const uint8_t *const end)
+{
+ int ret;
+
+ if ((ret = ptls_decode16(group, src, end)) != 0)
+ goto Exit;
+ ptls_decode_open_block(*src, end, 2, {
+ *key_exchange = ptls_iovec_init(*src, end - *src);
+ *src = end;
+ });
+
+Exit:
+ return ret;
+}
+
+static ptls_cipher_suite_t *find_cipher_suite(ptls_context_t *ctx, uint16_t id)
+{
+ ptls_cipher_suite_t **cs;
+
+ for (cs = ctx->cipher_suites; *cs != NULL && (*cs)->id != id; ++cs)
+ ;
+ return *cs;
+}
+
+static int decode_server_hello(ptls_t *tls, struct st_ptls_server_hello_t *sh, const uint8_t *src, const uint8_t *const end)
+{
+ int ret;
+
+ *sh = (struct st_ptls_server_hello_t){{0}};
+
+ /* ignore legacy-version */
+ if (end - src < 2) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ src += 2;
+
+ /* random */
+ if (end - src < PTLS_HELLO_RANDOM_SIZE) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ sh->is_retry_request = memcmp(src, hello_retry_random, PTLS_HELLO_RANDOM_SIZE) == 0;
+ src += PTLS_HELLO_RANDOM_SIZE;
+
+ /* legacy_session_id */
+ ptls_decode_open_block(src, end, 1, {
+ if (end - src > 32) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ sh->legacy_session_id = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+
+ { /* select cipher_suite */
+ uint16_t csid;
+ if ((ret = ptls_decode16(&csid, &src, end)) != 0)
+ goto Exit;
+ if ((tls->cipher_suite = find_cipher_suite(tls->ctx, csid)) == NULL) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ }
+
+ /* legacy_compression_method */
+ if (src == end || *src++ != 0) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+
+ if (sh->is_retry_request)
+ sh->retry_request.selected_group = UINT16_MAX;
+
+ uint16_t exttype, found_version = UINT16_MAX, selected_psk_identity = UINT16_MAX;
+ decode_extensions(src, end, PTLS_HANDSHAKE_TYPE_SERVER_HELLO, &exttype, {
+ switch (exttype) {
+ case PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS:
+ if ((ret = ptls_decode16(&found_version, &src, end)) != 0)
+ goto Exit;
+ break;
+ case PTLS_EXTENSION_TYPE_KEY_SHARE:
+ if (sh->is_retry_request) {
+ if ((ret = ptls_decode16(&sh->retry_request.selected_group, &src, end)) != 0)
+ goto Exit;
+ } else {
+ uint16_t group;
+ if ((ret = decode_key_share_entry(&group, &sh->peerkey, &src, end)) != 0)
+ goto Exit;
+ if (src != end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ if (tls->key_share == NULL || tls->key_share->id != group) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ }
+ break;
+ case PTLS_EXTENSION_TYPE_COOKIE:
+ if (sh->is_retry_request) {
+ ptls_decode_block(src, end, 2, {
+ if (src == end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ sh->retry_request.cookie = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ } else {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ break;
+ case PTLS_EXTENSION_TYPE_PRE_SHARED_KEY:
+ if (sh->is_retry_request) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ } else {
+ if ((ret = ptls_decode16(&selected_psk_identity, &src, end)) != 0)
+ goto Exit;
+ }
+ break;
+ default:
+ src = end;
+ break;
+ }
+ });
+
+ if (!is_supported_version(found_version)) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ if (!sh->is_retry_request) {
+ if (selected_psk_identity != UINT16_MAX) {
+ if (!tls->client.offered_psk) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ if (selected_psk_identity != 0) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ tls->is_psk_handshake = 1;
+ }
+ if (sh->peerkey.base == NULL && !tls->is_psk_handshake) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ }
+
+ ret = 0;
+Exit:
+ return ret;
+}
+
+static int handle_hello_retry_request(ptls_t *tls, ptls_buffer_t *sendbuf, struct st_ptls_server_hello_t *sh, ptls_iovec_t message,
+ ptls_handshake_properties_t *properties)
+{
+ int ret;
+
+ if (tls->client.key_share_ctx != NULL) {
+ tls->client.key_share_ctx->on_exchange(&tls->client.key_share_ctx, NULL, ptls_iovec_init(NULL, 0));
+ tls->client.key_share_ctx = NULL;
+ }
+
+ if (sh->retry_request.selected_group != UINT16_MAX) {
+ /* we offer the first key_exchanges[0] as KEY_SHARE unless client.negotiate_before_key_exchange is set */
+ ptls_key_exchange_algorithm_t **cand;
+ for (cand = tls->ctx->key_exchanges; *cand != NULL; ++cand)
+ if ((*cand)->id == sh->retry_request.selected_group)
+ break;
+ if (*cand == NULL) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ tls->key_share = *cand;
+ } else if (tls->key_share != NULL) {
+ /* retain the key-share using in first CH, if server does not specify one */
+ } else {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+
+ key_schedule_transform_post_ch1hash(tls->key_schedule);
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ ret = send_client_hello(tls, sendbuf, properties, &sh->retry_request.cookie);
+
+Exit:
+ return ret;
+}
+
+static int client_handle_hello(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t message, ptls_handshake_properties_t *properties)
+{
+ struct st_ptls_server_hello_t sh;
+ ptls_iovec_t ecdh_secret = {NULL};
+ int ret;
+
+ if ((ret = decode_server_hello(tls, &sh, message.base + PTLS_HANDSHAKE_HEADER_SIZE, message.base + message.len)) != 0)
+ goto Exit;
+ if (!(sh.legacy_session_id.len == sizeof(tls->client.legacy_session_id) &&
+ memcmp(sh.legacy_session_id.base, tls->client.legacy_session_id, sizeof(tls->client.legacy_session_id)) == 0)) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+
+ if (sh.is_retry_request) {
+ if ((ret = key_schedule_select_one(tls->key_schedule, tls->cipher_suite, 0)) != 0)
+ goto Exit;
+ return handle_hello_retry_request(tls, sendbuf, &sh, message, properties);
+ }
+
+ if ((ret = key_schedule_select_one(tls->key_schedule, tls->cipher_suite, tls->client.offered_psk && !tls->is_psk_handshake)) !=
+ 0)
+ goto Exit;
+
+ if (sh.peerkey.base != NULL) {
+ if ((ret = tls->client.key_share_ctx->on_exchange(&tls->client.key_share_ctx, &ecdh_secret, sh.peerkey)) != 0)
+ goto Exit;
+ }
+
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+
+ if ((ret = key_schedule_extract(tls->key_schedule, ecdh_secret)) != 0)
+ goto Exit;
+ if ((ret = setup_traffic_protection(tls, 0, "s hs traffic", "SERVER_HANDSHAKE_TRAFFIC_SECRET")) != 0)
+ goto Exit;
+
+ tls->state = PTLS_STATE_CLIENT_EXPECT_ENCRYPTED_EXTENSIONS;
+ ret = PTLS_ERROR_IN_PROGRESS;
+
+Exit:
+ if (ecdh_secret.base != NULL) {
+ ptls_clear_memory(ecdh_secret.base, ecdh_secret.len);
+ free(ecdh_secret.base);
+ }
+ return ret;
+}
+
+static int handle_unknown_extension(ptls_t *tls, ptls_handshake_properties_t *properties, uint16_t type, const uint8_t *src,
+ const uint8_t *const end, ptls_raw_extension_t *slots)
+{
+
+ if (properties != NULL && properties->collect_extension != NULL && properties->collect_extension(tls, properties, type)) {
+ size_t i;
+ for (i = 0; slots[i].type != UINT16_MAX; ++i) {
+ assert(i < MAX_UNKNOWN_EXTENSIONS);
+ if (slots[i].type == type)
+ return PTLS_ALERT_ILLEGAL_PARAMETER;
+ }
+ if (i < MAX_UNKNOWN_EXTENSIONS) {
+ slots[i].type = type;
+ slots[i].data = ptls_iovec_init(src, end - src);
+ slots[i + 1].type = UINT16_MAX;
+ }
+ }
+ return 0;
+}
+
+static int report_unknown_extensions(ptls_t *tls, ptls_handshake_properties_t *properties, ptls_raw_extension_t *slots)
+{
+ if (properties != NULL && properties->collect_extension != NULL) {
+ assert(properties->collected_extensions != NULL);
+ return properties->collected_extensions(tls, properties, slots);
+ } else {
+ return 0;
+ }
+}
+
+static int client_handle_encrypted_extensions(ptls_t *tls, ptls_iovec_t message, ptls_handshake_properties_t *properties)
+{
+ const uint8_t *src = message.base + PTLS_HANDSHAKE_HEADER_SIZE, *const end = message.base + message.len;
+ uint16_t type;
+ ptls_raw_extension_t unknown_extensions[MAX_UNKNOWN_EXTENSIONS + 1];
+ int ret, skip_early_data = 1;
+
+ unknown_extensions[0].type = UINT16_MAX;
+
+ decode_extensions(src, end, PTLS_HANDSHAKE_TYPE_ENCRYPTED_EXTENSIONS, &type, {
+ switch (type) {
+ case PTLS_EXTENSION_TYPE_SERVER_NAME:
+ if (src != end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ if (tls->server_name == NULL) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ break;
+ case PTLS_EXTENSION_TYPE_ALPN:
+ ptls_decode_block(src, end, 2, {
+ ptls_decode_open_block(src, end, 1, {
+ if ((ret = ptls_set_negotiated_protocol(tls, (const char *)src, end - src)) != 0)
+ goto Exit;
+ src = end;
+ });
+ if (src != end) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ });
+ break;
+ case PTLS_EXTENSION_TYPE_EARLY_DATA:
+ if (tls->early_data == NULL) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ skip_early_data = 0;
+ break;
+ default:
+ handle_unknown_extension(tls, properties, type, src, end, unknown_extensions);
+ break;
+ }
+ src = end;
+ });
+
+ if (tls->early_data != NULL) {
+ tls->skip_early_data = skip_early_data;
+ if (properties != NULL && !skip_early_data)
+ properties->client.early_data_accepted_by_peer = 1;
+ if ((ret = derive_secret(tls->key_schedule, tls->early_data->next_secret, "c hs traffic")) != 0)
+ goto Exit;
+ } else {
+ if ((ret = setup_traffic_protection(tls, 1, "c hs traffic", "CLIENT_HANDSHAKE_TRAFFIC_SECRET")) != 0)
+ goto Exit;
+ }
+ if ((ret = report_unknown_extensions(tls, properties, unknown_extensions)) != 0)
+ goto Exit;
+
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ tls->state = tls->is_psk_handshake ? PTLS_STATE_CLIENT_EXPECT_FINISHED : PTLS_STATE_CLIENT_EXPECT_CERTIFICATE;
+ ret = PTLS_ERROR_IN_PROGRESS;
+
+Exit:
+ return ret;
+}
+
+static int client_handle_certificate(ptls_t *tls, ptls_iovec_t message)
+{
+ const uint8_t *src = message.base + PTLS_HANDSHAKE_HEADER_SIZE, *const end = message.base + message.len;
+ ptls_iovec_t certs[16];
+ size_t num_certs = 0;
+ int ret;
+
+ /* certificate request context */
+ ptls_decode_open_block(src, end, 1, {
+ if (src != end) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ });
+ /* certificate_list */
+ ptls_decode_block(src, end, 3, {
+ do {
+ ptls_decode_open_block(src, end, 3, {
+ if (num_certs < sizeof(certs) / sizeof(certs[0]))
+ certs[num_certs++] = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ uint16_t type;
+ decode_open_extensions(src, end, PTLS_HANDSHAKE_TYPE_CERTIFICATE, &type, { src = end; });
+ } while (src != end);
+ });
+
+ if (tls->ctx->verify_certificate != NULL) {
+ if ((ret = tls->ctx->verify_certificate->cb(tls->ctx->verify_certificate, tls, &tls->client.certificate_verify.cb,
+ &tls->client.certificate_verify.verify_ctx, certs, num_certs)) != 0)
+ goto Exit;
+ }
+
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ tls->state = PTLS_STATE_CLIENT_EXPECT_CERTIFICATE_VERIFY;
+ ret = PTLS_ERROR_IN_PROGRESS;
+
+Exit:
+ return ret;
+}
+
+static int client_handle_certificate_verify(ptls_t *tls, ptls_iovec_t message)
+{
+ const uint8_t *src = message.base + PTLS_HANDSHAKE_HEADER_SIZE, *const end = message.base + message.len;
+ uint16_t algo;
+ ptls_iovec_t signature;
+ uint8_t signdata[PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE];
+ size_t signdata_size;
+ int ret;
+
+ /* decode */
+ if ((ret = ptls_decode16(&algo, &src, end)) != 0)
+ goto Exit;
+ ptls_decode_block(src, end, 2, {
+ signature = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+
+ /* validate */
+ switch (algo) {
+ case PTLS_SIGNATURE_RSA_PSS_RSAE_SHA256:
+ case PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256:
+ /* ok */
+ break;
+ default:
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ signdata_size = build_certificate_verify_signdata(signdata, tls->key_schedule, PTLS_SERVER_CERTIFICATE_VERIFY_CONTEXT_STRING);
+ if (tls->client.certificate_verify.cb != NULL) {
+ ret = tls->client.certificate_verify.cb(tls->client.certificate_verify.verify_ctx, ptls_iovec_init(signdata, signdata_size),
+ signature);
+ } else {
+ ret = 0;
+ }
+ ptls_clear_memory(signdata, signdata_size);
+ tls->client.certificate_verify.cb = NULL;
+ if (ret != 0)
+ goto Exit;
+
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ tls->state = PTLS_STATE_CLIENT_EXPECT_FINISHED;
+ ret = PTLS_ERROR_IN_PROGRESS;
+
+Exit:
+ return ret;
+}
+
+static int client_handle_finished(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t message)
+{
+ uint8_t send_secret[PTLS_MAX_DIGEST_SIZE];
+ int ret;
+
+ if ((ret = verify_finished(tls, message)) != 0)
+ goto Exit;
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+
+ /* update traffic keys by using messages upto ServerFinished, but commission them after sending ClientFinished */
+ if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0)
+ goto Exit;
+ if ((ret = setup_traffic_protection(tls, 0, "s ap traffic", "SERVER_TRAFFIC_SECRET_0")) != 0)
+ goto Exit;
+ if ((ret = derive_secret(tls->key_schedule, send_secret, "c ap traffic")) != 0)
+ goto Exit;
+ if ((ret = derive_exporter_secret(tls, 0)) != 0)
+ goto Exit;
+
+ /* if sending early data, emit EOED and commision the client handshake traffic secret */
+ if (tls->early_data != NULL) {
+ assert(tls->traffic_protection.enc.aead != NULL);
+ if (!tls->skip_early_data) {
+ buffer_push_handshake(sendbuf, tls->key_schedule, &tls->traffic_protection.enc, PTLS_HANDSHAKE_TYPE_END_OF_EARLY_DATA,
+ {});
+ }
+ if ((ret = retire_early_data_secret(tls, 1)) != 0)
+ goto Exit;
+ }
+
+ if ((ret = push_change_cipher_spec(tls, sendbuf)) != 0)
+ goto Exit;
+ ret = send_finished(tls, sendbuf);
+
+ memcpy(tls->traffic_protection.enc.secret, send_secret, sizeof(send_secret));
+ if ((ret = setup_traffic_protection(tls, 1, NULL, "CLIENT_TRAFFIC_SECRET_0")) != 0)
+ goto Exit;
+
+ tls->state = PTLS_STATE_CLIENT_POST_HANDSHAKE;
+
+Exit:
+ ptls_clear_memory(send_secret, sizeof(send_secret));
+ return ret;
+}
+
+static int client_handle_new_session_ticket(ptls_t *tls, ptls_iovec_t message)
+{
+ const uint8_t *src = message.base + PTLS_HANDSHAKE_HEADER_SIZE, *const end = message.base + message.len;
+ ptls_iovec_t ticket_nonce;
+ int ret;
+
+ { /* verify the format */
+ uint32_t ticket_lifetime, ticket_age_add, max_early_data_size;
+ ptls_iovec_t ticket;
+ if ((ret = decode_new_session_ticket(&ticket_lifetime, &ticket_age_add, &ticket_nonce, &ticket, &max_early_data_size, src,
+ end)) != 0)
+ return ret;
+ }
+
+ /* do nothing if use of session ticket is disabled */
+ if (tls->ctx->save_ticket == NULL)
+ return 0;
+
+ /* save the extension, along with the key of myself */
+ ptls_buffer_t ticket_buf;
+ uint8_t ticket_buf_small[512];
+ ptls_buffer_init(&ticket_buf, ticket_buf_small, sizeof(ticket_buf_small));
+ ptls_buffer_push64(&ticket_buf, tls->ctx->get_time->cb(tls->ctx->get_time));
+ ptls_buffer_push16(&ticket_buf, tls->key_share->id);
+ ptls_buffer_push16(&ticket_buf, tls->cipher_suite->id);
+ ptls_buffer_push_block(&ticket_buf, 3, { ptls_buffer_pushv(&ticket_buf, src, end - src); });
+ ptls_buffer_push_block(&ticket_buf, 2, {
+ if ((ret = ptls_buffer_reserve(&ticket_buf, tls->key_schedule->hashes[0].algo->digest_size)) != 0)
+ goto Exit;
+ if ((ret = derive_resumption_secret(tls->key_schedule, ticket_buf.base + ticket_buf.off, ticket_nonce)) != 0)
+ goto Exit;
+ ticket_buf.off += tls->key_schedule->hashes[0].algo->digest_size;
+ });
+
+ if ((ret = tls->ctx->save_ticket->cb(tls->ctx->save_ticket, tls, ptls_iovec_init(ticket_buf.base, ticket_buf.off))) != 0)
+ goto Exit;
+
+ ret = 0;
+Exit:
+ ptls_buffer_dispose(&ticket_buf);
+ return ret;
+}
+
+static int client_hello_decode_server_name(ptls_iovec_t *name, const uint8_t *src, const uint8_t *const end)
+{
+ int ret = 0;
+
+ ptls_decode_block(src, end, 2, {
+ if (src == end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ do {
+ uint8_t type = *src++;
+ ptls_decode_open_block(src, end, 2, {
+ switch (type) {
+ case PTLS_SERVER_NAME_TYPE_HOSTNAME:
+ if (memchr(src, '\0', end - src) != 0) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ *name = ptls_iovec_init(src, end - src);
+ break;
+ default:
+ break;
+ }
+ src = end;
+ });
+ } while (src != end);
+ });
+
+Exit:
+ return ret;
+}
+
+static int select_cipher_suite(ptls_cipher_suite_t **selected, ptls_cipher_suite_t **candidates, const uint8_t *src,
+ const uint8_t *const end)
+{
+ int ret;
+
+ ptls_decode_block(src, end, 2, {
+ while (src != end) {
+ uint16_t id;
+ if ((ret = ptls_decode16(&id, &src, end)) != 0)
+ goto Exit;
+ ptls_cipher_suite_t **c = candidates;
+ for (; *c != NULL; ++c) {
+ if ((*c)->id == id) {
+ *selected = *c;
+ return 0;
+ }
+ }
+ }
+ });
+
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+
+Exit:
+ return ret;
+}
+
+static int select_key_share(ptls_key_exchange_algorithm_t **selected, ptls_iovec_t *peer_key,
+ ptls_key_exchange_algorithm_t **candidates, const uint8_t *src, const uint8_t *const end)
+{
+ int ret;
+
+ ptls_decode_block(src, end, 2, {
+ while (src != end) {
+ uint16_t group;
+ ptls_iovec_t key;
+ if ((ret = decode_key_share_entry(&group, &key, &src, end)) != 0)
+ goto Exit;
+ ptls_key_exchange_algorithm_t **c = candidates;
+ for (; *c != NULL; ++c) {
+ if ((*c)->id == group) {
+ *selected = *c;
+ *peer_key = key;
+ return 0;
+ }
+ }
+ }
+ });
+
+ *selected = NULL;
+ ret = 0;
+
+Exit:
+ return ret;
+}
+
+static int select_negotiated_group(ptls_key_exchange_algorithm_t **selected, ptls_key_exchange_algorithm_t **candidates,
+ const uint8_t *src, const uint8_t *const end)
+{
+ int ret;
+
+ ptls_decode_block(src, end, 2, {
+ while (src != end) {
+ uint16_t group;
+ if ((ret = ptls_decode16(&group, &src, end)) != 0)
+ goto Exit;
+ ptls_key_exchange_algorithm_t **c = candidates;
+ for (; *c != NULL; ++c) {
+ if ((*c)->id == group) {
+ *selected = *c;
+ return 0;
+ }
+ }
+ }
+ });
+
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+
+Exit:
+ return ret;
+}
+
+static int decode_client_hello(ptls_t *tls, struct st_ptls_client_hello_t *ch, const uint8_t *src, const uint8_t *const end,
+ ptls_handshake_properties_t *properties)
+{
+ uint16_t exttype = 0;
+ int ret;
+
+ { /* check protocol version */
+ uint16_t protver;
+ if ((ret = ptls_decode16(&protver, &src, end)) != 0)
+ goto Exit;
+ if (protver != 0x0303) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ }
+
+ /* skip random */
+ if (end - src < PTLS_HELLO_RANDOM_SIZE) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ ch->random_bytes = src;
+ src += PTLS_HELLO_RANDOM_SIZE;
+
+ /* skip legacy_session_id */
+ ptls_decode_open_block(src, end, 1, {
+ if (end - src > 32) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ ch->legacy_session_id = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+
+ /* decode and select from ciphersuites */
+ ptls_decode_open_block(src, end, 2, {
+ ch->cipher_suites = ptls_iovec_init(src - 2, end - src + 2);
+ src = end;
+ });
+
+ /* decode legacy_compression_methods */
+ ptls_decode_open_block(src, end, 1, {
+ if (src == end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ ch->compression_methods.ids = src;
+ ch->compression_methods.count = end - src;
+ src = end;
+ });
+
+ /* decode extensions */
+ decode_extensions(src, end, PTLS_HANDSHAKE_TYPE_CLIENT_HELLO, &exttype, {
+ switch (exttype) {
+ case PTLS_EXTENSION_TYPE_SERVER_NAME:
+ if ((ret = client_hello_decode_server_name(&ch->server_name, src, end)) != 0)
+ goto Exit;
+ break;
+ case PTLS_EXTENSION_TYPE_ALPN:
+ ptls_decode_block(src, end, 2, {
+ do {
+ ptls_decode_open_block(src, end, 1, {
+ if (ch->alpn.count < sizeof(ch->alpn.list) / sizeof(ch->alpn.list[0]))
+ ch->alpn.list[ch->alpn.count++] = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ } while (src != end);
+ });
+ break;
+ case PTLS_EXTENSION_TYPE_SUPPORTED_GROUPS:
+ ch->negotiated_groups = ptls_iovec_init(src, end - src);
+ break;
+ case PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS:
+ ptls_decode_block(src, end, 2, {
+ do {
+ uint16_t id;
+ if ((ret = ptls_decode16(&id, &src, end)) != 0)
+ goto Exit;
+ if (ch->signature_algorithms.count <
+ sizeof(ch->signature_algorithms.list) / sizeof(ch->signature_algorithms.list[0]))
+ ch->signature_algorithms.list[ch->signature_algorithms.count++] = id;
+ } while (src != end);
+ });
+ break;
+ case PTLS_EXTENSION_TYPE_KEY_SHARE:
+ ch->key_shares = ptls_iovec_init(src, end - src);
+ break;
+ case PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS:
+ ptls_decode_block(src, end, 1, {
+ size_t selected_index = sizeof(supported_versions) / sizeof(supported_versions[0]);
+ do {
+ size_t i;
+ uint16_t v;
+ if ((ret = ptls_decode16(&v, &src, end)) != 0)
+ goto Exit;
+ for (i = 0; i != selected_index; ++i) {
+ if (supported_versions[i] == v) {
+ selected_index = i;
+ break;
+ }
+ }
+ } while (src != end);
+ if (selected_index != sizeof(supported_versions) / sizeof(supported_versions[0]))
+ ch->selected_version = supported_versions[selected_index];
+ });
+ break;
+ case PTLS_EXTENSION_TYPE_COOKIE:
+ if (properties->server.cookie.key == NULL) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ ch->cookie.all = ptls_iovec_init(src, end - src);
+ ptls_decode_block(src, end, 2, {
+ ch->cookie.tbs.base = (void *)src;
+ ptls_decode_open_block(src, end, 2, {
+ ptls_decode_open_block(src, end, 1, {
+ ch->cookie.ch1_hash = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ if (src == end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ switch (*src++) {
+ case 0:
+ assert(!ch->cookie.sent_key_share);
+ break;
+ case 1:
+ ch->cookie.sent_key_share = 1;
+ break;
+ default:
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ });
+ ch->cookie.tbs.len = src - ch->cookie.tbs.base;
+ ptls_decode_block(src, end, 1, {
+ ch->cookie.signature = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ });
+ break;
+ case PTLS_EXTENSION_TYPE_PRE_SHARED_KEY: {
+ size_t num_identities = 0;
+ ptls_decode_open_block(src, end, 2, {
+ do {
+ struct st_ptls_client_hello_psk_t psk = {{NULL}};
+ ptls_decode_open_block(src, end, 2, {
+ psk.identity = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ if ((ret = ptls_decode32(&psk.obfuscated_ticket_age, &src, end)) != 0)
+ goto Exit;
+ if (ch->psk.identities.count < sizeof(ch->psk.identities.list) / sizeof(ch->psk.identities.list[0]))
+ ch->psk.identities.list[ch->psk.identities.count++] = psk;
+ ++num_identities;
+ } while (src != end);
+ });
+ ch->psk.hash_end = src;
+ ptls_decode_block(src, end, 2, {
+ size_t num_binders = 0;
+ do {
+ ptls_decode_open_block(src, end, 1, {
+ if (num_binders < ch->psk.identities.count)
+ ch->psk.identities.list[num_binders].binder = ptls_iovec_init(src, end - src);
+ src = end;
+ });
+ ++num_binders;
+ } while (src != end);
+ if (num_identities != num_binders) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ });
+ } break;
+ case PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES:
+ ptls_decode_block(src, end, 1, {
+ if (src == end) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ for (; src != end; ++src) {
+ if (*src < sizeof(ch->psk.ke_modes) * 8)
+ ch->psk.ke_modes |= 1u << *src;
+ }
+ });
+ break;
+ case PTLS_EXTENSION_TYPE_EARLY_DATA:
+ ch->psk.early_data_indication = 1;
+ break;
+ case PTLS_EXTENSION_TYPE_STATUS_REQUEST:
+ ch->status_request = 1;
+ break;
+ default:
+ handle_unknown_extension(tls, properties, exttype, src, end, ch->unknown_extensions);
+ break;
+ }
+ src = end;
+ });
+
+ /* check if client hello make sense */
+ if (is_supported_version(ch->selected_version)) {
+ if (!(ch->compression_methods.count == 1 && ch->compression_methods.ids[0] == 0)) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ /* pre-shared key */
+ if (ch->psk.hash_end != NULL) {
+ /* PSK must be the last extension */
+ if (exttype != PTLS_EXTENSION_TYPE_PRE_SHARED_KEY) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ } else {
+ if (ch->psk.early_data_indication) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ }
+ } else {
+ ret = PTLS_ALERT_PROTOCOL_VERSION;
+ goto Exit;
+ }
+
+ ret = 0;
+Exit:
+ return ret;
+}
+
+static int vec_is_string(ptls_iovec_t x, const char *y)
+{
+ return strncmp((const char *)x.base, y, x.len) == 0 && y[x.len] == '\0';
+}
+
+static int try_psk_handshake(ptls_t *tls, size_t *psk_index, int *accept_early_data, struct st_ptls_client_hello_t *ch,
+ ptls_iovec_t ch_trunc)
+{
+ ptls_buffer_t decbuf;
+ ptls_iovec_t ticket_psk, ticket_server_name, ticket_negotiated_protocol;
+ uint64_t issue_at, now = tls->ctx->get_time->cb(tls->ctx->get_time);
+ uint32_t age_add;
+ uint16_t ticket_key_exchange_id, ticket_csid;
+ uint8_t decbuf_small[256], binder_key[PTLS_MAX_DIGEST_SIZE], verify_data[PTLS_MAX_DIGEST_SIZE];
+ int ret;
+
+ ptls_buffer_init(&decbuf, decbuf_small, sizeof(decbuf_small));
+
+ for (*psk_index = 0; *psk_index < ch->psk.identities.count; ++*psk_index) {
+ struct st_ptls_client_hello_psk_t *identity = ch->psk.identities.list + *psk_index;
+ /* decrypt and decode */
+ decbuf.off = 0;
+ if ((tls->ctx->encrypt_ticket->cb(tls->ctx->encrypt_ticket, tls, 0, &decbuf, identity->identity)) != 0)
+ continue;
+ if (decode_session_identifier(&issue_at, &ticket_psk, &age_add, &ticket_server_name, &ticket_key_exchange_id, &ticket_csid,
+ &ticket_negotiated_protocol, decbuf.base, decbuf.base + decbuf.off) != 0)
+ continue;
+ /* check age */
+ if (now < issue_at)
+ continue;
+ if (now - issue_at > (uint64_t)tls->ctx->ticket_lifetime * 1000)
+ continue;
+ *accept_early_data = 0;
+ if (ch->psk.early_data_indication) {
+ int64_t delta = (now - issue_at) - (identity->obfuscated_ticket_age - age_add);
+ if (delta <= PTLS_EARLY_DATA_MAX_DELAY)
+ *accept_early_data = 1;
+ }
+ /* check server-name */
+ if (ticket_server_name.len != 0) {
+ if (tls->server_name == NULL)
+ continue;
+ if (!vec_is_string(ticket_server_name, tls->server_name))
+ continue;
+ } else {
+ if (tls->server_name != NULL)
+ continue;
+ }
+ { /* check key-exchange */
+ ptls_key_exchange_algorithm_t **a;
+ for (a = tls->ctx->key_exchanges; *a != NULL && (*a)->id != ticket_key_exchange_id; ++a)
+ ;
+ if (*a == NULL)
+ continue;
+ tls->key_share = *a;
+ }
+ /* check cipher-suite */
+ if (ticket_csid != tls->cipher_suite->id)
+ continue;
+ /* check negotiated-protocol */
+ if (ticket_negotiated_protocol.len != 0) {
+ if (tls->negotiated_protocol == NULL)
+ continue;
+ if (!vec_is_string(ticket_negotiated_protocol, tls->negotiated_protocol))
+ continue;
+ }
+ /* check the length of the decrypted psk and the PSK binder */
+ if (ticket_psk.len != tls->key_schedule->hashes[0].algo->digest_size)
+ continue;
+ if (ch->psk.identities.list[*psk_index].binder.len != tls->key_schedule->hashes[0].algo->digest_size)
+ continue;
+
+ /* found */
+ goto Found;
+ }
+
+ /* not found */
+ *psk_index = SIZE_MAX;
+ *accept_early_data = 0;
+ tls->key_share = NULL;
+ ret = 0;
+ goto Exit;
+
+Found:
+ if ((ret = key_schedule_extract(tls->key_schedule, ticket_psk)) != 0)
+ goto Exit;
+ if ((ret = derive_secret(tls->key_schedule, binder_key, "res binder")) != 0)
+ goto Exit;
+ key_schedule_update_hash(tls->key_schedule, ch_trunc.base, ch_trunc.len);
+ if ((ret = calc_verify_data(verify_data, tls->key_schedule, binder_key)) != 0)
+ goto Exit;
+ if (memcmp(ch->psk.identities.list[*psk_index].binder.base, verify_data, tls->key_schedule->hashes[0].algo->digest_size) != 0) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ ret = 0;
+
+Exit:
+ ptls_buffer_dispose(&decbuf);
+ ptls_clear_memory(binder_key, sizeof(binder_key));
+ ptls_clear_memory(verify_data, sizeof(verify_data));
+ return ret;
+}
+
+static int calc_cookie_signature(ptls_t *tls, ptls_handshake_properties_t *properties,
+ ptls_key_exchange_algorithm_t *negotiated_group, ptls_iovec_t tbs, uint8_t *sig)
+{
+ ptls_hash_algorithm_t *algo = tls->ctx->cipher_suites[0]->hash;
+ ptls_hash_context_t *hctx;
+
+ if ((hctx = ptls_hmac_create(algo, properties->server.cookie.key, algo->digest_size)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+
+#define UPDATE_BLOCK(p, _len) \
+ do { \
+ size_t len = (_len); \
+ assert(len < UINT8_MAX); \
+ uint8_t len8 = (uint8_t)len; \
+ hctx->update(hctx, &len8, 1); \
+ hctx->update(hctx, (p), len); \
+ } while (0)
+#define UPDATE16(_v) \
+ do { \
+ uint16_t v = (_v); \
+ uint8_t b[2] = {v >> 8, v & 0xff}; \
+ hctx->update(hctx, b, 2); \
+ } while (0)
+
+ UPDATE_BLOCK(tls->client_random, sizeof(tls->client_random));
+ UPDATE_BLOCK(tls->server_name, tls->server_name != NULL ? strlen(tls->server_name) : 0);
+ UPDATE16(tls->cipher_suite->id);
+ UPDATE16(negotiated_group->id);
+ UPDATE_BLOCK(properties->server.cookie.additional_data.base, properties->server.cookie.additional_data.len);
+
+ UPDATE_BLOCK(tbs.base, tbs.len);
+
+#undef UPDATE_BLOCK
+#undef UPDATE16
+
+ hctx->final(hctx, sig, PTLS_HASH_FINAL_MODE_FREE);
+ return 0;
+}
+
+static int server_handle_hello(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t message, ptls_handshake_properties_t *properties)
+{
+#define EMIT_SERVER_HELLO(sched, fill_rand, extensions) \
+ buffer_push_handshake(sendbuf, (sched), NULL, PTLS_HANDSHAKE_TYPE_SERVER_HELLO, { \
+ ptls_buffer_push16(sendbuf, 0x0303 /* legacy version */); \
+ if ((ret = ptls_buffer_reserve(sendbuf, PTLS_HELLO_RANDOM_SIZE)) != 0) \
+ goto Exit; \
+ do { \
+ fill_rand \
+ } while (0); \
+ sendbuf->off += PTLS_HELLO_RANDOM_SIZE; \
+ ptls_buffer_push_block(sendbuf, 1, { ptls_buffer_pushv(sendbuf, ch.legacy_session_id.base, ch.legacy_session_id.len); }); \
+ ptls_buffer_push16(sendbuf, tls->cipher_suite->id); \
+ ptls_buffer_push(sendbuf, 0); \
+ ptls_buffer_push_block(sendbuf, 2, { \
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS, \
+ { ptls_buffer_push16(sendbuf, ch.selected_version); }); \
+ do { \
+ extensions \
+ } while (0); \
+ }); \
+ });
+
+#define EMIT_HELLO_RETRY_REQUEST(sched, negotiated_group, additional_extensions) \
+ EMIT_SERVER_HELLO((sched), { memcpy(sendbuf->base + sendbuf->off, hello_retry_random, PTLS_HELLO_RANDOM_SIZE); }, \
+ { \
+ ptls_key_exchange_algorithm_t *_negotiated_group = (negotiated_group); \
+ if (_negotiated_group != NULL) { \
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_KEY_SHARE, \
+ { ptls_buffer_push16(sendbuf, _negotiated_group->id); }); \
+ } \
+ do { \
+ additional_extensions \
+ } while (0); \
+ });
+
+ struct st_ptls_client_hello_t ch = {NULL, {NULL}, {NULL}, 0, {NULL}, {NULL}, {NULL},
+ {{0}}, {NULL}, {{{NULL}}}, {{NULL}}, {NULL}, {{UINT16_MAX}}};
+ struct {
+ ptls_key_exchange_algorithm_t *algorithm;
+ ptls_iovec_t peer_key;
+ } key_share = {NULL};
+ enum { HANDSHAKE_MODE_FULL, HANDSHAKE_MODE_PSK, HANDSHAKE_MODE_PSK_DHE } mode;
+ size_t psk_index = SIZE_MAX;
+ ptls_iovec_t pubkey = {0}, ecdh_secret = {0};
+ uint8_t finished_key[PTLS_MAX_DIGEST_SIZE];
+ int accept_early_data = 0, is_second_flight = tls->state == PTLS_STATE_SERVER_EXPECT_SECOND_CLIENT_HELLO, ret;
+
+ /* decode ClientHello */
+ if ((ret = decode_client_hello(tls, &ch, message.base + PTLS_HANDSHAKE_HEADER_SIZE, message.base + message.len, properties)) !=
+ 0)
+ goto Exit;
+ if (tls->ctx->require_dhe_on_psk)
+ ch.psk.ke_modes &= ~(1u << PTLS_PSK_KE_MODE_PSK);
+
+ /* handle client_random and SNI */
+ if (!is_second_flight) {
+ memcpy(tls->client_random, ch.random_bytes, sizeof(tls->client_random));
+ if (ch.server_name.base != NULL) {
+ if ((tls->server_name = malloc(ch.server_name.len + 1)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ memcpy(tls->server_name, ch.server_name.base, ch.server_name.len);
+ tls->server_name[ch.server_name.len] = '\0';
+ }
+ if (tls->ctx->on_client_hello != NULL &&
+ (ret = tls->ctx->on_client_hello->cb(tls->ctx->on_client_hello, tls, ch.server_name, ch.alpn.list, ch.alpn.count,
+ ch.signature_algorithms.list, ch.signature_algorithms.count)) != 0)
+ goto Exit;
+ } else {
+ if (ch.psk.early_data_indication) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ if (memcmp(tls->client_random, ch.random_bytes, sizeof(tls->client_random)) != 0 ||
+ (tls->server_name != NULL) != (ch.server_name.base != NULL) ||
+ (tls->server_name != NULL &&
+ !(strncmp(tls->server_name, (char *)ch.server_name.base, ch.server_name.len) == 0 &&
+ tls->server_name[ch.server_name.len] == '\0'))) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ }
+
+ { /* select (or check) cipher-suite, create key_schedule */
+ ptls_cipher_suite_t *cs;
+ if ((ret = select_cipher_suite(&cs, tls->ctx->cipher_suites, ch.cipher_suites.base,
+ ch.cipher_suites.base + ch.cipher_suites.len)) != 0)
+ goto Exit;
+ if (!is_second_flight) {
+ tls->cipher_suite = cs;
+ tls->key_schedule = key_schedule_new(cs, NULL);
+ } else {
+ if (tls->cipher_suite != cs) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ }
+ }
+
+ /* select key_share */
+ if (ch.key_shares.base != NULL &&
+ (ret = select_key_share(&key_share.algorithm, &key_share.peer_key, tls->ctx->key_exchanges, ch.key_shares.base,
+ ch.key_shares.base + ch.key_shares.len)) != 0)
+ goto Exit;
+
+ if (!is_second_flight) {
+ if (ch.cookie.all.len != 0 && key_share.algorithm != NULL) {
+
+ /* use cookie to check the integrity of the handshake, and update the context */
+ uint8_t sig[PTLS_MAX_DIGEST_SIZE];
+ size_t sigsize = tls->ctx->cipher_suites[0]->hash->digest_size;
+ if ((ret = calc_cookie_signature(tls, properties, key_share.algorithm, ch.cookie.tbs, sig)) != 0)
+ goto Exit;
+ if (!(ch.cookie.signature.len == sigsize && memcmp(ch.cookie.signature.base, sig, sigsize) == 0)) {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ goto Exit;
+ }
+ /* integrity check passed; update states */
+ key_schedule_update_ch1hash_prefix(tls->key_schedule);
+ key_schedule_update_hash(tls->key_schedule, ch.cookie.ch1_hash.base, ch.cookie.ch1_hash.len);
+ key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0));
+ /* ... reusing sendbuf to rebuild HRR for hash calculation */
+ size_t hrr_start = sendbuf->off;
+ EMIT_HELLO_RETRY_REQUEST(tls->key_schedule, ch.cookie.sent_key_share ? key_share.algorithm : NULL, {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_COOKIE,
+ { ptls_buffer_pushv(sendbuf, ch.cookie.all.base, ch.cookie.all.len); });
+ });
+ sendbuf->off = hrr_start;
+ is_second_flight = 1;
+
+ } else if (key_share.algorithm == NULL || (properties != NULL && properties->server.enforce_retry)) {
+
+ /* send HelloRetryRequest */
+ if (ch.negotiated_groups.base == NULL) {
+ ret = PTLS_ALERT_MISSING_EXTENSION;
+ goto Exit;
+ }
+ ptls_key_exchange_algorithm_t *negotiated_group;
+ if ((ret = select_negotiated_group(&negotiated_group, tls->ctx->key_exchanges, ch.negotiated_groups.base,
+ ch.negotiated_groups.base + ch.negotiated_groups.len)) != 0)
+ goto Exit;
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ assert(tls->key_schedule->generation == 0);
+ if (properties != NULL && properties->server.retry_uses_cookie) {
+ /* emit HRR with cookie (note: we MUST omit KeyShare if the client has specified the correct one; see 46554f0) */
+ EMIT_HELLO_RETRY_REQUEST(NULL, key_share.algorithm != NULL ? NULL : negotiated_group, {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_COOKIE, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ /* push to-be-signed data */
+ size_t tbs_start = sendbuf->off;
+ ptls_buffer_push_block(sendbuf, 2, {
+ /* first block of the cookie data is the hash(ch1) */
+ ptls_buffer_push_block(sendbuf, 1, {
+ size_t sz = tls->cipher_suite->hash->digest_size;
+ if ((ret = ptls_buffer_reserve(sendbuf, sz)) != 0)
+ goto Exit;
+ key_schedule_extract_ch1hash(tls->key_schedule, sendbuf->base + sendbuf->off);
+ sendbuf->off += sz;
+ });
+ /* second is if we have sent key_share extension */
+ ptls_buffer_push(sendbuf, key_share.algorithm == NULL);
+ /* we can add more data here */
+ });
+ size_t tbs_len = sendbuf->off - tbs_start;
+ /* push the signature */
+ ptls_buffer_push_block(sendbuf, 1, {
+ size_t sz = tls->ctx->cipher_suites[0]->hash->digest_size;
+ if ((ret = ptls_buffer_reserve(sendbuf, sz)) != 0)
+ goto Exit;
+ if ((ret = calc_cookie_signature(tls, properties, negotiated_group,
+ ptls_iovec_init(sendbuf->base + tbs_start, tbs_len),
+ sendbuf->base + sendbuf->off)) != 0)
+ goto Exit;
+ sendbuf->off += sz;
+ });
+ });
+ });
+ });
+ if ((ret = push_change_cipher_spec(tls, sendbuf)) != 0)
+ goto Exit;
+ ret = PTLS_ERROR_STATELESS_RETRY;
+ } else {
+ /* invoking stateful retry; roll the key schedule and emit HRR */
+ key_schedule_transform_post_ch1hash(tls->key_schedule);
+ key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0));
+ EMIT_HELLO_RETRY_REQUEST(tls->key_schedule, key_share.algorithm != NULL ? NULL : negotiated_group, {});
+ if ((ret = push_change_cipher_spec(tls, sendbuf)) != 0)
+ goto Exit;
+ tls->state = PTLS_STATE_SERVER_EXPECT_SECOND_CLIENT_HELLO;
+ if (ch.psk.early_data_indication)
+ tls->skip_early_data = 1;
+ ret = PTLS_ERROR_IN_PROGRESS;
+ }
+ goto Exit;
+ }
+ }
+
+ /* handle unknown extensions */
+ if ((ret = report_unknown_extensions(tls, properties, ch.unknown_extensions)) != 0)
+ goto Exit;
+
+ /* try psk handshake */
+ if (!is_second_flight && ch.psk.hash_end != 0 &&
+ (ch.psk.ke_modes & ((1u << PTLS_PSK_KE_MODE_PSK) | (1u << PTLS_PSK_KE_MODE_PSK_DHE))) != 0 &&
+ tls->ctx->encrypt_ticket != NULL) {
+ if ((ret = try_psk_handshake(tls, &psk_index, &accept_early_data, &ch,
+ ptls_iovec_init(message.base, ch.psk.hash_end - message.base))) != 0)
+ goto Exit;
+ }
+
+ /* adjust key_schedule, determine handshake mode */
+ if (psk_index == SIZE_MAX) {
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ if (!is_second_flight) {
+ assert(tls->key_schedule->generation == 0);
+ key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0));
+ }
+ mode = HANDSHAKE_MODE_FULL;
+ if (properties != NULL)
+ properties->server.selected_psk_binder.len = 0;
+ } else {
+ key_schedule_update_hash(tls->key_schedule, ch.psk.hash_end, message.base + message.len - ch.psk.hash_end);
+ if ((ch.psk.ke_modes & (1u << PTLS_PSK_KE_MODE_PSK)) != 0) {
+ mode = HANDSHAKE_MODE_PSK;
+ } else {
+ assert((ch.psk.ke_modes & (1u << PTLS_PSK_KE_MODE_PSK_DHE)) != 0);
+ mode = HANDSHAKE_MODE_PSK_DHE;
+ }
+ tls->is_psk_handshake = 1;
+ if (properties != NULL) {
+ ptls_iovec_t *selected = &ch.psk.identities.list[psk_index].binder;
+ memcpy(properties->server.selected_psk_binder.base, selected->base, selected->len);
+ properties->server.selected_psk_binder.len = selected->len;
+ }
+ if ((ret = derive_exporter_secret(tls, 1)) != 0)
+ goto Exit;
+ }
+
+ if (accept_early_data && tls->ctx->max_early_data_size != 0 && psk_index == 0) {
+ if ((tls->early_data = malloc(sizeof(*tls->early_data))) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((ret = setup_traffic_protection(tls, 0, "c e traffic", "CLIENT_EARLY_TRAFFIC_SECRET")) != 0)
+ goto Exit;
+ }
+
+ /* run key-exchange, to obtain pubkey and secret */
+ if (mode != HANDSHAKE_MODE_PSK) {
+ if (key_share.algorithm == NULL) {
+ ret = ch.key_shares.base != NULL ? PTLS_ALERT_HANDSHAKE_FAILURE : PTLS_ALERT_MISSING_EXTENSION;
+ goto Exit;
+ }
+ if ((ret = key_share.algorithm->exchange(&pubkey, &ecdh_secret, key_share.peer_key)) != 0)
+ goto Exit;
+ tls->key_share = key_share.algorithm;
+ }
+
+ /* send ServerHello */
+ EMIT_SERVER_HELLO(tls->key_schedule, { tls->ctx->random_bytes(sendbuf->base + sendbuf->off, PTLS_HELLO_RANDOM_SIZE); },
+ {
+ if (mode != HANDSHAKE_MODE_PSK) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_KEY_SHARE, {
+ ptls_buffer_push16(sendbuf, key_share.algorithm->id);
+ ptls_buffer_push_block(sendbuf, 2, { ptls_buffer_pushv(sendbuf, pubkey.base, pubkey.len); });
+ });
+ }
+ if (mode != HANDSHAKE_MODE_FULL) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_PRE_SHARED_KEY,
+ { ptls_buffer_push16(sendbuf, (uint16_t)psk_index); });
+ }
+ });
+ if ((ret = push_change_cipher_spec(tls, sendbuf)) != 0)
+ goto Exit;
+
+ /* create protection contexts for the handshake */
+ assert(tls->key_schedule->generation == 1);
+ key_schedule_extract(tls->key_schedule, ecdh_secret);
+ if ((ret = setup_traffic_protection(tls, 1, "s hs traffic", "SERVER_HANDSHAKE_TRAFFIC_SECRET")) != 0)
+ goto Exit;
+ if (tls->early_data != NULL) {
+ if ((ret = derive_secret(tls->key_schedule, tls->early_data->next_secret, "c hs traffic")) != 0)
+ goto Exit;
+ } else {
+ if ((ret = setup_traffic_protection(tls, 0, "c hs traffic", "CLIENT_HANDSHAKE_TRAFFIC_SECRET")) != 0)
+ goto Exit;
+ if (ch.psk.early_data_indication)
+ tls->skip_early_data = 1;
+ }
+
+ /* send EncryptedExtensions */
+ buffer_push_handshake(sendbuf, tls->key_schedule, &tls->traffic_protection.enc, PTLS_HANDSHAKE_TYPE_ENCRYPTED_EXTENSIONS, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ if (tls->server_name != NULL) {
+ /* In this event, the server SHALL include an extension of type "server_name" in the (extended) server
+ * hello. The "extension_data" field of this extension SHALL be empty. (RFC 6066 section 3) */
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SERVER_NAME, {});
+ }
+ if (tls->negotiated_protocol != NULL) {
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_ALPN, {
+ ptls_buffer_push_block(sendbuf, 2, {
+ ptls_buffer_push_block(sendbuf, 1, {
+ ptls_buffer_pushv(sendbuf, tls->negotiated_protocol, strlen(tls->negotiated_protocol));
+ });
+ });
+ });
+ }
+ if (tls->early_data != NULL && tls->traffic_protection.dec.aead != NULL)
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_EARLY_DATA, {});
+ if ((ret = push_additional_extensions(properties, sendbuf)) != 0)
+ goto Exit;
+ });
+ });
+
+ if (mode == HANDSHAKE_MODE_FULL) {
+ if (ch.signature_algorithms.count == 0) {
+ ret = PTLS_ALERT_MISSING_EXTENSION;
+ goto Exit;
+ }
+ /* send Certificate */
+ buffer_push_handshake(sendbuf, tls->key_schedule, &tls->traffic_protection.enc, PTLS_HANDSHAKE_TYPE_CERTIFICATE, {
+ ptls_buffer_push(sendbuf, 0);
+ ptls_buffer_push_block(sendbuf, 3, {
+ size_t i;
+ for (i = 0; i != tls->ctx->certificates.count; ++i) {
+ ptls_buffer_push_block(sendbuf, 3, {
+ ptls_buffer_pushv(sendbuf, tls->ctx->certificates.list[i].base, tls->ctx->certificates.list[i].len);
+ });
+ ptls_buffer_push_block(sendbuf, 2, {
+ /* emit OCSP stapling only when requested and when the callback successfully returns one */
+ if (ch.status_request && i == 0 && tls->ctx->staple_ocsp != NULL) {
+ size_t reset_off_to = sendbuf->off;
+ buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_STATUS_REQUEST, {
+ ptls_buffer_push(sendbuf, 1); /* status_type == ocsp */
+ ptls_buffer_push_block(sendbuf, 3, {
+ if ((ret = tls->ctx->staple_ocsp->cb(tls->ctx->staple_ocsp, tls, sendbuf, i)) == 0)
+ reset_off_to = 0;
+ });
+ });
+ if (reset_off_to != 0)
+ sendbuf->off = reset_off_to;
+ }
+ });
+ }
+ });
+ });
+ /* build and send CertificateVerify */
+ buffer_push_handshake(sendbuf, tls->key_schedule, &tls->traffic_protection.enc, PTLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY, {
+ size_t algo_off = sendbuf->off;
+ ptls_buffer_push16(sendbuf, 0); /* filled in later */
+ ptls_buffer_push_block(sendbuf, 2, {
+ uint16_t algo;
+ uint8_t data[PTLS_MAX_CERTIFICATE_VERIFY_SIGNDATA_SIZE];
+ size_t datalen =
+ build_certificate_verify_signdata(data, tls->key_schedule, PTLS_SERVER_CERTIFICATE_VERIFY_CONTEXT_STRING);
+ if ((ret = tls->ctx->sign_certificate->cb(tls->ctx->sign_certificate, tls, &algo, sendbuf,
+ ptls_iovec_init(data, datalen), ch.signature_algorithms.list,
+ ch.signature_algorithms.count)) != 0)
+ goto Exit;
+ sendbuf->base[algo_off] = (uint8_t)(algo >> 8);
+ sendbuf->base[algo_off + 1] = (uint8_t)algo;
+ });
+ });
+ }
+
+ send_finished(tls, sendbuf);
+
+ assert(tls->key_schedule->generation == 2);
+ if ((ret = key_schedule_extract(tls->key_schedule, ptls_iovec_init(NULL, 0))) != 0)
+ goto Exit;
+ if ((ret = setup_traffic_protection(tls, 1, "s ap traffic", "SERVER_TRAFFIC_SECRET_0")) != 0)
+ goto Exit;
+ if ((ret = derive_secret(tls->key_schedule, tls->server.pending_traffic_secret, "c ap traffic")) != 0)
+ goto Exit;
+ if ((ret = derive_exporter_secret(tls, 0)) != 0)
+ goto Exit;
+
+ tls->state = tls->early_data != NULL ? PTLS_STATE_SERVER_EXPECT_END_OF_EARLY_DATA : PTLS_STATE_SERVER_EXPECT_FINISHED;
+
+ /* send session ticket if necessary */
+ if (ch.psk.ke_modes != 0 && tls->ctx->ticket_lifetime != 0) {
+ if ((ret = send_session_ticket(tls, sendbuf)) != 0)
+ goto Exit;
+ }
+
+ ret = 0;
+
+Exit:
+ free(pubkey.base);
+ free(ecdh_secret.base);
+ ptls_clear_memory(finished_key, sizeof(finished_key));
+ return ret;
+
+#undef EMIT_SERVER_HELLO
+#undef EMIT_HELLO_RETRY_REQUEST
+}
+
+static int server_handle_end_of_early_data(ptls_t *tls, ptls_iovec_t message)
+{
+ int ret;
+
+ if ((ret = retire_early_data_secret(tls, 0)) != 0)
+ goto Exit;
+
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+ tls->state = PTLS_STATE_SERVER_EXPECT_FINISHED;
+ ret = PTLS_ERROR_IN_PROGRESS;
+
+Exit:
+ return ret;
+}
+
+static int server_handle_finished(ptls_t *tls, ptls_iovec_t message)
+{
+ int ret;
+
+ if ((ret = verify_finished(tls, message)) != 0)
+ return ret;
+
+ memcpy(tls->traffic_protection.dec.secret, tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret));
+ ptls_clear_memory(tls->server.pending_traffic_secret, sizeof(tls->server.pending_traffic_secret));
+ if ((ret = setup_traffic_protection(tls, 0, NULL, "CLIENT_TRAFFIC_SECRET_0")) != 0)
+ return ret;
+
+ key_schedule_update_hash(tls->key_schedule, message.base, message.len);
+
+ tls->state = PTLS_STATE_SERVER_POST_HANDSHAKE;
+ return 0;
+}
+
+static int parse_record_header(struct st_ptls_record_t *rec, const uint8_t *src)
+{
+ rec->type = src[0];
+ rec->version = ntoh16(src + 1);
+ rec->length = ntoh16(src + 3);
+
+ if (rec->length >
+ (size_t)(rec->type == PTLS_CONTENT_TYPE_APPDATA ? PTLS_MAX_ENCRYPTED_RECORD_SIZE : PTLS_MAX_PLAINTEXT_RECORD_SIZE))
+ return PTLS_ALERT_DECODE_ERROR;
+
+ return 0;
+}
+
+static int parse_record(ptls_t *tls, struct st_ptls_record_t *rec, const uint8_t *src, size_t *len)
+{
+ int ret;
+
+ if (tls->recvbuf.rec.base == NULL && *len >= 5) {
+ /* fast path */
+ if ((ret = parse_record_header(rec, src)) != 0)
+ return ret;
+ if (5 + rec->length <= *len) {
+ rec->fragment = src + 5;
+ *len = rec->length + 5;
+ return 0;
+ }
+ }
+
+ /* slow path */
+ const uint8_t *const end = src + *len;
+ *rec = (struct st_ptls_record_t){0};
+
+ if (tls->recvbuf.rec.base == NULL) {
+ ptls_buffer_init(&tls->recvbuf.rec, "", 0);
+ if ((ret = ptls_buffer_reserve(&tls->recvbuf.rec, 5)) != 0)
+ return ret;
+ }
+
+ /* fill and parse the header */
+ while (tls->recvbuf.rec.off < 5) {
+ if (src == end)
+ return PTLS_ERROR_IN_PROGRESS;
+ tls->recvbuf.rec.base[tls->recvbuf.rec.off++] = *src++;
+ }
+ if ((ret = parse_record_header(rec, tls->recvbuf.rec.base)) != 0)
+ return ret;
+
+ /* fill the fragment */
+ size_t addlen = rec->length + 5 - tls->recvbuf.rec.off;
+ if (addlen != 0) {
+ if ((ret = ptls_buffer_reserve(&tls->recvbuf.rec, addlen)) != 0)
+ return ret;
+ if (addlen > (size_t)(end - src))
+ addlen = end - src;
+ if (addlen != 0) {
+ memcpy(tls->recvbuf.rec.base + tls->recvbuf.rec.off, src, addlen);
+ tls->recvbuf.rec.off += addlen;
+ src += addlen;
+ }
+ }
+
+ /* set rec->fragment if a complete record has been parsed */
+ if (tls->recvbuf.rec.off == rec->length + 5) {
+ rec->fragment = tls->recvbuf.rec.base + 5;
+ ret = 0;
+ } else {
+ ret = PTLS_ERROR_IN_PROGRESS;
+ }
+
+ *len -= end - src;
+ return ret;
+}
+
+static void update_open_count(ptls_context_t *ctx, ssize_t delta)
+{
+ if (ctx->update_open_count != NULL)
+ ctx->update_open_count->cb(ctx->update_open_count, delta);
+}
+
+ptls_t *ptls_new(ptls_context_t *ctx, int is_server)
+{
+ ptls_t *tls;
+
+ assert(ctx->get_time != NULL && "please set ctx->get_time to `&ptls_get_time`; see #92");
+
+ if ((tls = malloc(sizeof(*tls))) == NULL)
+ return NULL;
+
+ update_open_count(ctx, 1);
+ *tls = (ptls_t){ctx};
+ tls->is_server = is_server;
+ tls->send_change_cipher_spec = ctx->send_change_cipher_spec;
+ if (!is_server) {
+ tls->state = PTLS_STATE_CLIENT_HANDSHAKE_START;
+ tls->ctx->random_bytes(tls->client_random, sizeof(tls->client_random));
+ tls->ctx->random_bytes(tls->client.legacy_session_id, sizeof(tls->client.legacy_session_id));
+ } else {
+ tls->state = PTLS_STATE_SERVER_EXPECT_CLIENT_HELLO;
+ }
+
+ return tls;
+}
+
+void ptls_free(ptls_t *tls)
+{
+ ptls_buffer_dispose(&tls->recvbuf.rec);
+ ptls_buffer_dispose(&tls->recvbuf.mess);
+ free_exporter_master_secret(tls, 1);
+ free_exporter_master_secret(tls, 0);
+ if (tls->key_schedule != NULL)
+ key_schedule_free(tls->key_schedule);
+ if (tls->traffic_protection.dec.aead != NULL)
+ ptls_aead_free(tls->traffic_protection.dec.aead);
+ if (tls->traffic_protection.enc.aead != NULL)
+ ptls_aead_free(tls->traffic_protection.enc.aead);
+ free(tls->server_name);
+ free(tls->negotiated_protocol);
+ if (tls->is_server) {
+ /* nothing to do */
+ } else {
+ if (tls->client.key_share_ctx != NULL)
+ tls->client.key_share_ctx->on_exchange(&tls->client.key_share_ctx, NULL, ptls_iovec_init(NULL, 0));
+ if (tls->client.certificate_verify.cb != NULL)
+ tls->client.certificate_verify.cb(tls->client.certificate_verify.verify_ctx, ptls_iovec_init(NULL, 0),
+ ptls_iovec_init(NULL, 0));
+ }
+ if (tls->early_data != NULL) {
+ ptls_clear_memory(tls->early_data, sizeof(*tls->early_data));
+ free(tls->early_data);
+ }
+ update_open_count(tls->ctx, -1);
+ ptls_clear_memory(tls, sizeof(*tls));
+ free(tls);
+}
+
+ptls_context_t *ptls_get_context(ptls_t *tls)
+{
+ return tls->ctx;
+}
+
+void ptls_set_context(ptls_t *tls, ptls_context_t *ctx)
+{
+ update_open_count(ctx, 1);
+ update_open_count(tls->ctx, -1);
+ tls->ctx = ctx;
+}
+
+ptls_iovec_t ptls_get_client_random(ptls_t *tls)
+{
+ return ptls_iovec_init(tls->client_random, PTLS_HELLO_RANDOM_SIZE);
+}
+
+ptls_cipher_suite_t *ptls_get_cipher(ptls_t *tls)
+{
+ return tls->cipher_suite;
+}
+
+const char *ptls_get_server_name(ptls_t *tls)
+{
+ return tls->server_name;
+}
+
+int ptls_set_server_name(ptls_t *tls, const char *server_name, size_t server_name_len)
+{
+ char *duped = NULL;
+
+ if (server_name != NULL) {
+ if (server_name_len == 0)
+ server_name_len = strlen(server_name);
+ if ((duped = malloc(server_name_len + 1)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ memcpy(duped, server_name, server_name_len);
+ duped[server_name_len] = '\0';
+ }
+
+ free(tls->server_name);
+ tls->server_name = duped;
+
+ return 0;
+}
+
+const char *ptls_get_negotiated_protocol(ptls_t *tls)
+{
+ return tls->negotiated_protocol;
+}
+
+int ptls_set_negotiated_protocol(ptls_t *tls, const char *protocol, size_t protocol_len)
+{
+ char *duped = NULL;
+
+ if (protocol != NULL) {
+ if (protocol_len == 0)
+ protocol_len = strlen(protocol);
+ if ((duped = malloc(protocol_len + 1)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ memcpy(duped, protocol, protocol_len);
+ duped[protocol_len] = '\0';
+ }
+
+ free(tls->negotiated_protocol);
+ tls->negotiated_protocol = duped;
+
+ return 0;
+}
+
+int ptls_handshake_is_complete(ptls_t *tls)
+{
+ return tls->state >= PTLS_STATE_POST_HANDSHAKE_MIN;
+}
+
+int ptls_is_psk_handshake(ptls_t *tls)
+{
+ return tls->is_psk_handshake;
+}
+
+void **ptls_get_data_ptr(ptls_t *tls)
+{
+ return &tls->data_ptr;
+}
+
+static int handle_handshake_message(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t message, int is_end_of_record,
+ ptls_handshake_properties_t *properties)
+{
+ uint8_t type = message.base[0];
+ int ret;
+
+ switch (tls->state) {
+ case PTLS_STATE_CLIENT_EXPECT_SERVER_HELLO:
+ case PTLS_STATE_CLIENT_EXPECT_SECOND_SERVER_HELLO:
+ if (type == PTLS_HANDSHAKE_TYPE_SERVER_HELLO && is_end_of_record) {
+ ret = client_handle_hello(tls, sendbuf, message, properties);
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_STATE_CLIENT_EXPECT_ENCRYPTED_EXTENSIONS:
+ if (type == PTLS_HANDSHAKE_TYPE_ENCRYPTED_EXTENSIONS) {
+ ret = client_handle_encrypted_extensions(tls, message, properties);
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_STATE_CLIENT_EXPECT_CERTIFICATE:
+ if (type == PTLS_HANDSHAKE_TYPE_CERTIFICATE) {
+ ret = client_handle_certificate(tls, message);
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_STATE_CLIENT_EXPECT_CERTIFICATE_VERIFY:
+ if (type == PTLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) {
+ ret = client_handle_certificate_verify(tls, message);
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_STATE_CLIENT_EXPECT_FINISHED:
+ if (type == PTLS_HANDSHAKE_TYPE_FINISHED && is_end_of_record) {
+ ret = client_handle_finished(tls, sendbuf, message);
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_STATE_SERVER_EXPECT_CLIENT_HELLO:
+ case PTLS_STATE_SERVER_EXPECT_SECOND_CLIENT_HELLO:
+ if (type == PTLS_HANDSHAKE_TYPE_CLIENT_HELLO && is_end_of_record) {
+ ret = server_handle_hello(tls, sendbuf, message, properties);
+ } else {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ }
+ break;
+ case PTLS_STATE_SERVER_EXPECT_END_OF_EARLY_DATA:
+ if (type == PTLS_HANDSHAKE_TYPE_END_OF_EARLY_DATA) {
+ ret = server_handle_end_of_early_data(tls, message);
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_STATE_SERVER_EXPECT_FINISHED:
+ if (type == PTLS_HANDSHAKE_TYPE_FINISHED && is_end_of_record) {
+ ret = server_handle_finished(tls, message);
+ } else {
+ ret = PTLS_ALERT_HANDSHAKE_FAILURE;
+ }
+ break;
+ case PTLS_STATE_CLIENT_POST_HANDSHAKE:
+ switch (type) {
+ case PTLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET:
+ ret = client_handle_new_session_ticket(tls, message);
+ break;
+ default:
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ break;
+ }
+ break;
+ case PTLS_STATE_SERVER_POST_HANDSHAKE:
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ break;
+ default:
+ assert(!"unexpected state");
+ break;
+ }
+
+ return ret;
+}
+
+static int handle_alert(ptls_t *tls, const uint8_t *src, size_t len)
+{
+ if (len != 2)
+ return PTLS_ALERT_DECODE_ERROR;
+
+ uint8_t level = src[0], desc = src[1];
+
+ /* ignore certain warnings */
+ if (level == PTLS_ALERT_LEVEL_WARNING) {
+ switch (desc) {
+ case PTLS_ALERT_USER_CANCELED:
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ /* all other alerts are considered fatal, regardless of the transmitted level (section 6) */
+ return PTLS_ALERT_TO_PEER_ERROR(desc);
+}
+
+static int handle_handshake_record(ptls_t *tls, int (*cb)(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t message,
+ int is_end_of_record, ptls_handshake_properties_t *properties),
+ ptls_buffer_t *sendbuf, struct st_ptls_record_t *rec, ptls_handshake_properties_t *properties)
+{
+ int ret;
+
+ /* handshake */
+ if (rec->type != PTLS_CONTENT_TYPE_HANDSHAKE)
+ return PTLS_ALERT_DECODE_ERROR;
+
+ /* flatten the unhandled messages */
+ const uint8_t *src, *src_end;
+ if (tls->recvbuf.mess.base == NULL) {
+ src = rec->fragment;
+ src_end = src + rec->length;
+ } else {
+ if ((ret = ptls_buffer_reserve(&tls->recvbuf.mess, rec->length)) != 0)
+ return ret;
+ memcpy(tls->recvbuf.mess.base + tls->recvbuf.mess.off, rec->fragment, rec->length);
+ tls->recvbuf.mess.off += rec->length;
+ src = tls->recvbuf.mess.base;
+ src_end = src + tls->recvbuf.mess.off;
+ }
+
+ /* handle the messages */
+ ret = PTLS_ERROR_IN_PROGRESS;
+ while (src_end - src >= 4) {
+ size_t mess_len = 4 + ntoh24(src + 1);
+ if (src_end - src < (int)mess_len)
+ break;
+ ret = cb(tls, sendbuf, ptls_iovec_init(src, mess_len), src_end - src == mess_len, properties);
+ switch (ret) {
+ case 0:
+ case PTLS_ERROR_IN_PROGRESS:
+ break;
+ default:
+ ptls_buffer_dispose(&tls->recvbuf.mess);
+ return ret;
+ }
+ src += mess_len;
+ }
+
+ /* keep last partial message in buffer */
+ if (src != src_end) {
+ if (tls->recvbuf.mess.base == NULL) {
+ ptls_buffer_init(&tls->recvbuf.mess, "", 0);
+ if ((ret = ptls_buffer_reserve(&tls->recvbuf.mess, src_end - src)) != 0)
+ return ret;
+ memcpy(tls->recvbuf.mess.base, src, src_end - src);
+ } else {
+ memmove(tls->recvbuf.mess.base, src, src_end - src);
+ }
+ tls->recvbuf.mess.off = src_end - src;
+ ret = PTLS_ERROR_IN_PROGRESS;
+ } else {
+ ptls_buffer_dispose(&tls->recvbuf.mess);
+ }
+
+ return ret;
+}
+
+static int handle_input(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_buffer_t *decryptbuf, const void *input, size_t *inlen,
+ ptls_handshake_properties_t *properties)
+{
+ struct st_ptls_record_t rec;
+ int ret;
+
+ /* extract the record */
+ if ((ret = parse_record(tls, &rec, input, inlen)) != 0)
+ return ret;
+ assert(rec.fragment != NULL);
+
+ /* decrypt the record */
+ if (rec.type == PTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
+ if (tls->state < PTLS_STATE_POST_HANDSHAKE_MIN) {
+ if (!(rec.length == 1 && rec.fragment[0] == 0x01))
+ return PTLS_ALERT_ILLEGAL_PARAMETER;
+ } else {
+ return PTLS_ALERT_HANDSHAKE_FAILURE;
+ }
+ ret = PTLS_ERROR_IN_PROGRESS;
+ goto NextRecord;
+ }
+ if (tls->traffic_protection.dec.aead != NULL && rec.type != PTLS_CONTENT_TYPE_ALERT) {
+ if (rec.type != PTLS_CONTENT_TYPE_APPDATA)
+ return PTLS_ALERT_HANDSHAKE_FAILURE;
+ if ((ret = ptls_buffer_reserve(decryptbuf, 5 + rec.length)) != 0)
+ return ret;
+ if ((ret = aead_decrypt(&tls->traffic_protection.dec, decryptbuf->base + decryptbuf->off, &rec.length, rec.fragment,
+ rec.length)) != 0) {
+ if (tls->skip_early_data) {
+ ret = PTLS_ERROR_IN_PROGRESS;
+ goto NextRecord;
+ }
+ return ret;
+ }
+ rec.fragment = decryptbuf->base + decryptbuf->off;
+ /* skip padding */
+ for (; rec.length != 0; --rec.length)
+ if (rec.fragment[rec.length - 1] != 0)
+ break;
+ if (rec.length == 0)
+ return PTLS_ALERT_UNEXPECTED_MESSAGE;
+ rec.type = rec.fragment[--rec.length];
+ } else if (rec.type == PTLS_CONTENT_TYPE_APPDATA && tls->skip_early_data) {
+ ret = PTLS_ERROR_IN_PROGRESS;
+ goto NextRecord;
+ }
+
+ if (tls->recvbuf.mess.base != NULL || rec.type == PTLS_CONTENT_TYPE_HANDSHAKE) {
+ /* handshake record */
+ ret = handle_handshake_record(tls, handle_handshake_message, sendbuf, &rec, properties);
+ } else {
+ /* handling of an alert or an application record */
+ switch (rec.type) {
+ case PTLS_CONTENT_TYPE_APPDATA:
+ if (tls->state >= PTLS_STATE_POST_HANDSHAKE_MIN) {
+ decryptbuf->off += rec.length;
+ ret = 0;
+ } else if (tls->state == PTLS_STATE_SERVER_EXPECT_END_OF_EARLY_DATA) {
+ if (tls->traffic_protection.dec.aead != NULL)
+ decryptbuf->off += rec.length;
+ ret = 0;
+ } else {
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ }
+ break;
+ case PTLS_CONTENT_TYPE_ALERT:
+ ret = handle_alert(tls, rec.fragment, rec.length);
+ break;
+ default:
+ ret = PTLS_ALERT_UNEXPECTED_MESSAGE;
+ break;
+ }
+ }
+
+NextRecord:
+ ptls_buffer_dispose(&tls->recvbuf.rec);
+ return ret;
+}
+
+int ptls_handshake(ptls_t *tls, ptls_buffer_t *sendbuf, const void *input, size_t *inlen, ptls_handshake_properties_t *properties)
+{
+ size_t sendbuf_orig_off = sendbuf->off;
+ int ret;
+
+ assert(tls->state < PTLS_STATE_POST_HANDSHAKE_MIN);
+
+ /* special handlings */
+ switch (tls->state) {
+ case PTLS_STATE_CLIENT_HANDSHAKE_START:
+ assert(input == NULL || *inlen == 0);
+ assert(tls->ctx->key_exchanges[0] != NULL);
+ return send_client_hello(tls, sendbuf, properties, NULL);
+ default:
+ break;
+ }
+
+ const uint8_t *src = input, *const src_end = src + *inlen;
+ ptls_buffer_t decryptbuf;
+ uint8_t decryptbuf_small[256];
+
+ ptls_buffer_init(&decryptbuf, decryptbuf_small, sizeof(decryptbuf_small));
+
+ /* perform handhake until completion or until all the input has been swallowed */
+ ret = PTLS_ERROR_IN_PROGRESS;
+ while (ret == PTLS_ERROR_IN_PROGRESS && src != src_end) {
+ size_t consumed = src_end - src;
+ ret = handle_input(tls, sendbuf, &decryptbuf, src, &consumed, properties);
+ src += consumed;
+ assert(decryptbuf.off == 0);
+ }
+
+ ptls_buffer_dispose(&decryptbuf);
+
+ switch (ret) {
+ case 0:
+ case PTLS_ERROR_IN_PROGRESS:
+ case PTLS_ERROR_STATELESS_RETRY:
+ break;
+ default:
+ /* flush partially written response */
+ ptls_clear_memory(sendbuf->base + sendbuf_orig_off, sendbuf->off - sendbuf_orig_off);
+ sendbuf->off = sendbuf_orig_off;
+ /* send alert immediately */
+ if (PTLS_ERROR_GET_CLASS(ret) != PTLS_ERROR_CLASS_PEER_ALERT)
+ if (ptls_send_alert(tls, sendbuf, PTLS_ALERT_LEVEL_FATAL,
+ PTLS_ERROR_GET_CLASS(ret) == PTLS_ERROR_CLASS_SELF_ALERT ? ret : PTLS_ALERT_INTERNAL_ERROR) != 0)
+ sendbuf->off = sendbuf_orig_off;
+ break;
+ }
+
+ *inlen -= src_end - src;
+ return ret;
+}
+
+int ptls_receive(ptls_t *tls, ptls_buffer_t *decryptbuf, const void *_input, size_t *inlen)
+{
+ const uint8_t *input = (const uint8_t *)_input, *const end = input + *inlen;
+ size_t decryptbuf_orig_size = decryptbuf->off;
+ int ret = 0;
+
+ assert(tls->state >= PTLS_STATE_SERVER_EXPECT_END_OF_EARLY_DATA);
+
+ /* loop until we decrypt some application data (or an error) */
+ while (ret == 0 && input != end && decryptbuf_orig_size == decryptbuf->off) {
+ size_t consumed = end - input;
+ ret = handle_input(tls, NULL, decryptbuf, input, &consumed, NULL);
+ input += consumed;
+
+ switch (ret) {
+ case 0:
+ break;
+ case PTLS_ERROR_IN_PROGRESS:
+ ret = 0;
+ break;
+ case PTLS_ERROR_CLASS_PEER_ALERT + PTLS_ALERT_CLOSE_NOTIFY:
+ /* TODO send close alert */
+ break;
+ default:
+ if (PTLS_ERROR_GET_CLASS(ret) == PTLS_ERROR_CLASS_SELF_ALERT) {
+ /* TODO send alert */
+ }
+ break;
+ }
+ }
+
+ *inlen -= end - input;
+
+ return ret;
+}
+
+int ptls_send(ptls_t *tls, ptls_buffer_t *sendbuf, const void *input, size_t inlen)
+{
+ assert(tls->traffic_protection.enc.aead != NULL);
+ return buffer_push_encrypted_records(sendbuf, PTLS_CONTENT_TYPE_APPDATA, input, inlen, &tls->traffic_protection.enc);
+}
+
+size_t ptls_get_record_overhead(ptls_t *tls)
+{
+ return 6 + tls->traffic_protection.enc.aead->algo->tag_size;
+}
+
+int ptls_send_alert(ptls_t *tls, ptls_buffer_t *sendbuf, uint8_t level, uint8_t description)
+{
+ size_t rec_start = sendbuf->off;
+ int ret = 0;
+
+ buffer_push_record(sendbuf, PTLS_CONTENT_TYPE_ALERT, { ptls_buffer_push(sendbuf, level, description); });
+ /* encrypt the alert if we have the encryption keys, unless when it is the early data key */
+ if (tls->traffic_protection.enc.aead != NULL && !(tls->state <= PTLS_STATE_CLIENT_EXPECT_FINISHED)) {
+ if ((ret = buffer_encrypt_record(sendbuf, rec_start, &tls->traffic_protection.enc)) != 0)
+ goto Exit;
+ }
+
+Exit:
+ return ret;
+}
+
+int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *label, ptls_iovec_t context_value, int is_early)
+{
+ ptls_hash_algorithm_t *algo = tls->key_schedule->hashes[0].algo;
+ ptls_hash_context_t *hctx;
+ uint8_t *master_secret = is_early ? tls->exporter_master_secret.early : tls->exporter_master_secret.one_rtt,
+ derived_secret[PTLS_MAX_DIGEST_SIZE], context_value_hash[PTLS_MAX_DIGEST_SIZE];
+ int ret;
+
+ if (master_secret == NULL)
+ return PTLS_ERROR_IN_PROGRESS;
+
+ if ((hctx = algo->create()) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ hctx->update(hctx, context_value.base, context_value.len);
+ hctx->final(hctx, context_value_hash, PTLS_HASH_FINAL_MODE_FREE);
+
+ if ((ret = ptls_hkdf_expand_label(algo, derived_secret, algo->digest_size, ptls_iovec_init(master_secret, algo->digest_size),
+ label, ptls_iovec_init(algo->empty_digest, algo->digest_size), NULL)) != 0)
+ goto Exit;
+ ret = ptls_hkdf_expand_label(algo, output, outlen, ptls_iovec_init(derived_secret, algo->digest_size), "exporter",
+ ptls_iovec_init(context_value_hash, algo->digest_size), NULL);
+
+Exit:
+ ptls_clear_memory(derived_secret, sizeof(derived_secret));
+ ptls_clear_memory(context_value_hash, sizeof(context_value_hash));
+ return ret;
+}
+
+struct st_picotls_hmac_context_t {
+ ptls_hash_context_t super;
+ ptls_hash_algorithm_t *algo;
+ ptls_hash_context_t *hash;
+ uint8_t key[1];
+};
+
+static void hmac_update(ptls_hash_context_t *_ctx, const void *src, size_t len)
+{
+ struct st_picotls_hmac_context_t *ctx = (struct st_picotls_hmac_context_t *)_ctx;
+ ctx->hash->update(ctx->hash, src, len);
+}
+
+static void hmac_apply_key(struct st_picotls_hmac_context_t *ctx, uint8_t pad)
+{
+ size_t i;
+
+ for (i = 0; i != ctx->algo->block_size; ++i)
+ ctx->key[i] ^= pad;
+ ctx->hash->update(ctx->hash, ctx->key, ctx->algo->block_size);
+ for (i = 0; i != ctx->algo->block_size; ++i)
+ ctx->key[i] ^= pad;
+}
+
+static void hmac_final(ptls_hash_context_t *_ctx, void *md, ptls_hash_final_mode_t mode)
+{
+ struct st_picotls_hmac_context_t *ctx = (struct st_picotls_hmac_context_t *)_ctx;
+
+ assert(mode != PTLS_HASH_FINAL_MODE_SNAPSHOT || !"not supported");
+
+ if (md != NULL) {
+ ctx->hash->final(ctx->hash, md, PTLS_HASH_FINAL_MODE_RESET);
+ hmac_apply_key(ctx, 0x5c);
+ ctx->hash->update(ctx->hash, md, ctx->algo->digest_size);
+ }
+ ctx->hash->final(ctx->hash, md, mode);
+
+ switch (mode) {
+ case PTLS_HASH_FINAL_MODE_FREE:
+ ptls_clear_memory(ctx->key, ctx->algo->block_size);
+ free(ctx);
+ break;
+ case PTLS_HASH_FINAL_MODE_RESET:
+ hmac_apply_key(ctx, 0x36);
+ break;
+ default:
+ assert(!"FIXME");
+ break;
+ }
+}
+
+ptls_hash_context_t *ptls_hmac_create(ptls_hash_algorithm_t *algo, const void *key, size_t key_size)
+{
+ struct st_picotls_hmac_context_t *ctx;
+
+ if ((ctx = malloc(offsetof(struct st_picotls_hmac_context_t, key) + algo->block_size)) == NULL)
+ return NULL;
+
+ *ctx = (struct st_picotls_hmac_context_t){{hmac_update, hmac_final}, algo};
+ if ((ctx->hash = algo->create()) == NULL) {
+ free(ctx);
+ return NULL;
+ }
+ memset(ctx->key, 0, algo->block_size);
+ memcpy(ctx->key, key, key_size);
+
+ hmac_apply_key(ctx, 0x36);
+
+ return &ctx->super;
+}
+
+int ptls_hkdf_extract(ptls_hash_algorithm_t *algo, void *output, ptls_iovec_t salt, ptls_iovec_t ikm)
+{
+ ptls_hash_context_t *hash;
+
+ if (salt.len == 0)
+ salt = ptls_iovec_init(zeroes_of_max_digest_size, algo->digest_size);
+
+ if ((hash = ptls_hmac_create(algo, salt.base, salt.len)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ hash->update(hash, ikm.base, ikm.len);
+ hash->final(hash, output, PTLS_HASH_FINAL_MODE_FREE);
+ return 0;
+}
+
+int ptls_hkdf_expand(ptls_hash_algorithm_t *algo, void *output, size_t outlen, ptls_iovec_t prk, ptls_iovec_t info)
+{
+ ptls_hash_context_t *hmac = NULL;
+ size_t i;
+ uint8_t digest[PTLS_MAX_DIGEST_SIZE];
+
+ for (i = 0; (i * algo->digest_size) < outlen; ++i) {
+ if (hmac == NULL) {
+ if ((hmac = ptls_hmac_create(algo, prk.base, prk.len)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ } else {
+ hmac->update(hmac, digest, algo->digest_size);
+ }
+ hmac->update(hmac, info.base, info.len);
+ uint8_t gen = (uint8_t)(i + 1);
+ hmac->update(hmac, &gen, 1);
+ hmac->final(hmac, digest, 1);
+
+ size_t off_start = i * algo->digest_size, off_end = off_start + algo->digest_size;
+ if (off_end > outlen)
+ off_end = outlen;
+ memcpy((uint8_t *)output + off_start, digest, off_end - off_start);
+ }
+
+ if (hmac != NULL)
+ hmac->final(hmac, NULL, PTLS_HASH_FINAL_MODE_FREE);
+
+ ptls_clear_memory(digest, algo->digest_size);
+
+ return 0;
+}
+
+int ptls_hkdf_expand_label(ptls_hash_algorithm_t *algo, void *output, size_t outlen, ptls_iovec_t secret, const char *label,
+ ptls_iovec_t hash_value, const char *base_label)
+{
+ ptls_buffer_t hkdf_label;
+ uint8_t hkdf_label_buf[512];
+ int ret;
+
+ ptls_buffer_init(&hkdf_label, hkdf_label_buf, sizeof(hkdf_label_buf));
+
+ ptls_buffer_push16(&hkdf_label, (uint16_t)outlen);
+ ptls_buffer_push_block(&hkdf_label, 1, {
+ if (base_label == NULL)
+ base_label = "tls13 ";
+ ptls_buffer_pushv(&hkdf_label, base_label, strlen(base_label));
+ ptls_buffer_pushv(&hkdf_label, label, strlen(label));
+ });
+ ptls_buffer_push_block(&hkdf_label, 1, { ptls_buffer_pushv(&hkdf_label, hash_value.base, hash_value.len); });
+
+ ret = ptls_hkdf_expand(algo, output, outlen, secret, ptls_iovec_init(hkdf_label.base, hkdf_label.off));
+
+Exit:
+ ptls_buffer_dispose(&hkdf_label);
+ return ret;
+}
+
+ptls_cipher_context_t *ptls_cipher_new(ptls_cipher_algorithm_t *algo, int is_enc, const void *key)
+{
+ ptls_cipher_context_t *ctx;
+
+ if ((ctx = (ptls_cipher_context_t *)malloc(algo->context_size)) == NULL)
+ return NULL;
+ *ctx = (ptls_cipher_context_t){algo};
+ if (algo->setup_crypto(ctx, is_enc, key) != 0) {
+ free(ctx);
+ ctx = NULL;
+ }
+ return ctx;
+}
+
+void ptls_cipher_free(ptls_cipher_context_t *ctx)
+{
+ ctx->do_dispose(ctx);
+ free(ctx);
+}
+
+ptls_aead_context_t *ptls_aead_new(ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t *hash, int is_enc, const void *secret,
+ const char *base_label)
+{
+ ptls_aead_context_t *ctx;
+ uint8_t key[PTLS_MAX_SECRET_SIZE];
+ int ret;
+
+ if ((ctx = (ptls_aead_context_t *)malloc(aead->context_size)) == NULL)
+ return NULL;
+
+ *ctx = (ptls_aead_context_t){aead};
+ if ((ret = get_traffic_key(hash, key, aead->key_size, 0, secret, base_label)) != 0)
+ goto Exit;
+ if ((ret = get_traffic_key(hash, ctx->static_iv, aead->iv_size, 1, secret, base_label)) != 0)
+ goto Exit;
+ ret = aead->setup_crypto(ctx, is_enc, key);
+
+Exit:
+ ptls_clear_memory(key, aead->key_size);
+ if (ret != 0) {
+ ptls_clear_memory(ctx->static_iv, aead->iv_size);
+ free(ctx);
+ ctx = NULL;
+ }
+
+ return ctx;
+}
+
+void ptls_aead_free(ptls_aead_context_t *ctx)
+{
+ ctx->dispose_crypto(ctx);
+ ptls_clear_memory(ctx->static_iv, ctx->algo->iv_size);
+ free(ctx);
+}
+
+size_t ptls_aead_encrypt(ptls_aead_context_t *ctx, void *output, const void *input, size_t inlen, uint64_t seq, const void *aad,
+ size_t aadlen)
+{
+ size_t off = 0;
+
+ ptls_aead_encrypt_init(ctx, seq, aad, aadlen);
+ off += ptls_aead_encrypt_update(ctx, ((uint8_t *)output) + off, input, inlen);
+ off += ptls_aead_encrypt_final(ctx, ((uint8_t *)output) + off);
+
+ return off;
+}
+
+void ptls_aead__build_iv(ptls_aead_context_t *ctx, uint8_t *iv, uint64_t seq)
+{
+ size_t iv_size = ctx->algo->iv_size, i;
+ const uint8_t *s = ctx->static_iv;
+ uint8_t *d = iv;
+
+ /* build iv */
+ for (i = iv_size - 8; i != 0; --i)
+ *d++ = *s++;
+ i = 64;
+ do {
+ i -= 8;
+ *d++ = *s++ ^ (uint8_t)(seq >> i);
+ } while (i != 0);
+}
+
+static void clear_memory(void *p, size_t len)
+{
+ if (len != 0)
+ memset(p, 0, len);
+}
+
+void (*volatile ptls_clear_memory)(void *p, size_t len) = clear_memory;
+
+static uint64_t get_time(ptls_get_time_t *self)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+ptls_get_time_t ptls_get_time = {get_time};
+
diff --git a/web/server/h2o/libh2o/deps/picotls/lib/uecc.c b/web/server/h2o/libh2o/deps/picotls/lib/uecc.c
new file mode 100644
index 00000000..10f32520
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/lib/uecc.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WINDOWS
+#include "wincompat.h"
+#else
+#include <unistd.h>
+#endif
+#include "sha2.h"
+#include "uECC.h"
+#include "uECC_vli.h"
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+
+#define TYPE_UNCOMPRESSED_PUBLIC_KEY 4
+
+struct st_secp256r1_key_exhchange_t {
+ ptls_key_exchange_context_t super;
+ uint8_t priv[SECP256R1_PRIVATE_KEY_SIZE];
+ uint8_t pub[SECP256R1_PUBLIC_KEY_SIZE];
+};
+
+static int secp256r1_on_exchange(ptls_key_exchange_context_t **_ctx, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ struct st_secp256r1_key_exhchange_t *ctx = (struct st_secp256r1_key_exhchange_t *)*_ctx;
+ uint8_t *secbytes = NULL;
+ int ret;
+
+ *_ctx = NULL;
+
+ if (secret == NULL) {
+ ret = 0;
+ goto Exit;
+ }
+
+ if (peerkey.len != SECP256R1_PUBLIC_KEY_SIZE || peerkey.base[0] != TYPE_UNCOMPRESSED_PUBLIC_KEY) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ if ((secbytes = (uint8_t *)malloc(SECP256R1_SHARED_SECRET_SIZE)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if (!uECC_shared_secret(peerkey.base + 1, ctx->priv, secbytes, uECC_secp256r1())) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ *secret = ptls_iovec_init(secbytes, SECP256R1_SHARED_SECRET_SIZE);
+ ret = 0;
+
+Exit:
+ if (ret != 0)
+ free(secbytes);
+ ptls_clear_memory(ctx->priv, sizeof(ctx->priv));
+ free(ctx);
+ return ret;
+}
+
+static int secp256r1_create_key_exchange(ptls_key_exchange_context_t **_ctx, ptls_iovec_t *pubkey)
+{
+ struct st_secp256r1_key_exhchange_t *ctx;
+
+ if ((ctx = (struct st_secp256r1_key_exhchange_t *)malloc(sizeof(*ctx))) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+ ctx->super = (ptls_key_exchange_context_t){secp256r1_on_exchange};
+ ctx->pub[0] = TYPE_UNCOMPRESSED_PUBLIC_KEY;
+ uECC_make_key(ctx->pub + 1, ctx->priv, uECC_secp256r1());
+
+ *_ctx = &ctx->super;
+ *pubkey = ptls_iovec_init(ctx->pub, sizeof(ctx->pub));
+ return 0;
+}
+
+static int secp256r1_key_exchange(ptls_iovec_t *pubkey, ptls_iovec_t *secret, ptls_iovec_t peerkey)
+{
+ uint8_t priv[SECP256R1_PRIVATE_KEY_SIZE], *pub = NULL, *secbytes = NULL;
+ int ret;
+
+ if (peerkey.len != SECP256R1_PUBLIC_KEY_SIZE || peerkey.base[0] != TYPE_UNCOMPRESSED_PUBLIC_KEY) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ if ((pub = malloc(SECP256R1_PUBLIC_KEY_SIZE)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+ if ((secbytes = malloc(SECP256R1_SHARED_SECRET_SIZE)) == NULL) {
+ ret = PTLS_ERROR_NO_MEMORY;
+ goto Exit;
+ }
+
+ pub[0] = TYPE_UNCOMPRESSED_PUBLIC_KEY;
+ uECC_make_key(pub + 1, priv, uECC_secp256r1());
+ if (!uECC_shared_secret(peerkey.base + 1, priv, secbytes, uECC_secp256r1())) {
+ ret = PTLS_ALERT_DECRYPT_ERROR;
+ goto Exit;
+ }
+ *pubkey = ptls_iovec_init(pub, SECP256R1_PUBLIC_KEY_SIZE);
+ *secret = ptls_iovec_init(secbytes, SECP256R1_SHARED_SECRET_SIZE);
+ ret = 0;
+
+Exit:
+ ptls_clear_memory(priv, sizeof(priv));
+ if (ret != 0) {
+ free(secbytes);
+ free(pub);
+ }
+ return ret;
+}
+
+static int secp256r1sha256_sign(ptls_sign_certificate_t *_self, ptls_t *tls, uint16_t *selected_algorithm, ptls_buffer_t *outbuf,
+ ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms)
+{
+ ptls_minicrypto_secp256r1sha256_sign_certificate_t *self = (ptls_minicrypto_secp256r1sha256_sign_certificate_t *)_self;
+ uint8_t hash[32], sig[64];
+ size_t i;
+ int ret;
+
+ /* check algorithm */
+ for (i = 0; i != num_algorithms; ++i)
+ if (algorithms[i] == PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256)
+ break;
+ if (i == num_algorithms)
+ return PTLS_ALERT_HANDSHAKE_FAILURE;
+
+ { /* calc hash */
+ cf_sha256_context ctx;
+ cf_sha256_init(&ctx);
+ cf_sha256_update(&ctx, input.base, input.len);
+ cf_sha256_digest_final(&ctx, hash);
+ ptls_clear_memory(&ctx, sizeof(ctx));
+ }
+
+ /* sign */
+ uECC_sign(self->key, hash, sizeof(hash), sig, uECC_secp256r1());
+
+ /* encode using DER */
+ ptls_buffer_push_asn1_sequence(outbuf, {
+ if ((ret = ptls_buffer_push_asn1_ubigint(outbuf, sig, 32)) != 0)
+ goto Exit;
+ if ((ret = ptls_buffer_push_asn1_ubigint(outbuf, sig + 32, 32)) != 0)
+ goto Exit;
+ });
+
+ *selected_algorithm = PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256;
+ ret = 0;
+
+Exit:
+ ptls_clear_memory(hash, sizeof(hash));
+ ptls_clear_memory(sig, sizeof(sig));
+ return ret;
+}
+
+int ptls_minicrypto_init_secp256r1sha256_sign_certificate(ptls_minicrypto_secp256r1sha256_sign_certificate_t *self,
+ ptls_iovec_t key)
+{
+ if (key.len != sizeof(self->key))
+ return PTLS_ERROR_INCOMPATIBLE_KEY;
+
+ self->super.cb = secp256r1sha256_sign;
+ memcpy(self->key, key.base, sizeof(self->key));
+
+ return 0;
+}
+
+ptls_key_exchange_algorithm_t ptls_minicrypto_secp256r1 = {PTLS_GROUP_SECP256R1, secp256r1_create_key_exchange,
+ secp256r1_key_exchange};
+ptls_key_exchange_algorithm_t *ptls_minicrypto_key_exchanges[] = {&ptls_minicrypto_secp256r1, NULL};
diff --git a/web/server/h2o/libh2o/deps/picotls/misc/dump-github-repository.pl b/web/server/h2o/libh2o/deps/picotls/misc/dump-github-repository.pl
new file mode 100755
index 00000000..ab811575
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/misc/dump-github-repository.pl
@@ -0,0 +1,41 @@
+#! /usr/bin/perl
+
+use strict;
+use warnings;
+use Errno ();
+use File::Basename qw(basename);
+
+die "Usage: $0 <https://github.com/user/repo> <commit> <dest-dir> [<path>]\n"
+ if @ARGV < 3;
+
+my ($repo, $commit, $dest, $path) = @ARGV;
+my $strip_components = 1;
+my ($rm_path, $tar_path);
+
+if (defined $path) {
+ $path =~ s|/*$||;
+ $strip_components += scalar(split "/", $path) - 1;
+ $rm_path = "$dest/" . basename $path;
+ $tar_path = "*/$path";
+} else {
+ $path = "";
+ $rm_path = "$dest";
+ $tar_path = "";
+}
+
+run("rm -rf $rm_path");
+
+mkdir("$dest")
+ or $! == Errno::EEXIST or die "failed to (re)create directory:$dest:$!";
+run("curl --silent --show-error --location $repo/archive/$commit.tar.gz | (cd $dest && tar x --strip-components $strip_components -zf - $tar_path)") == 0
+ or die "failed to extract $repo/archive/$commit.tar.gz to $dest";
+run("git add -f `find $rm_path -type f`") == 0
+ or die "failed to add files under $dest";
+run("git commit --allow-empty -m 'extract $repo @ $commit @{[defined $path ? qq{($path)} : '']} at $dest' $dest") == 0
+ or die "failed to commit";
+
+sub run {
+ my $cmd = shift;
+ print "$cmd\n";
+ system($cmd);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.pbxproj b/web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..881b8f44
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.pbxproj
@@ -0,0 +1,1023 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 105900431DC8D57000FB4085 /* picotls.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530E91D9B7C13005B2C60 /* picotls.c */; };
+ 105900441DC8D57000FB4085 /* picotest.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530E31D9B4021005B2C60 /* picotest.c */; };
+ 1059004C1DC8D5B700FB4085 /* openssl.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530C51D9B1A98005B2C60 /* openssl.c */; };
+ 1059004E1DC8D61800FB4085 /* minicrypto.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059003D1DC8D4E300FB4085 /* minicrypto.c */; };
+ 105900501DC8D64E00FB4085 /* minicrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059004F1DC8D64E00FB4085 /* minicrypto.h */; };
+ 105900611DC8DF8C00FB4085 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059005F1DC8DE4400FB4085 /* sha256.c */; };
+ 105900641DC8DFA700FB4085 /* curve25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900391DC8D46A00FB4085 /* curve25519.c */; };
+ 105900691DC8DFDF00FB4085 /* blockwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900291DC8D39800FB4085 /* blockwise.c */; };
+ 1059006A1DC8DFE300FB4085 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900651DC8DFD300FB4085 /* hmac.c */; };
+ 1059006F1DC8E00B00FB4085 /* chash.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059006B1DC8E00400FB4085 /* chash.c */; };
+ 105900761DC8E1A300FB4085 /* openssl.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530C21D9B004B005B2C60 /* openssl.c */; };
+ 1059008F1DC8E1FF00FB4085 /* aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900251DC8D37500FB4085 /* aes.h */; };
+ 105900911DC8E1FF00FB4085 /* bitops.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900281DC8D39800FB4085 /* bitops.h */; };
+ 105900921DC8E1FF00FB4085 /* blockwise.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059002A1DC8D39800FB4085 /* blockwise.h */; };
+ 105900941DC8E1FF00FB4085 /* chash.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059006C1DC8E00400FB4085 /* chash.h */; };
+ 105900961DC8E1FF00FB4085 /* curve25519.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900361DC8D44E00FB4085 /* curve25519.h */; };
+ 105900991DC8E1FF00FB4085 /* cf_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900321DC8D41A00FB4085 /* cf_config.h */; };
+ 1059009A1DC8E1FF00FB4085 /* drbg.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900521DC8D79300FB4085 /* drbg.h */; };
+ 1059009C1DC8E1FF00FB4085 /* handy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059002B1DC8D39800FB4085 /* handy.h */; };
+ 1059009D1DC8E1FF00FB4085 /* hmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900661DC8DFD300FB4085 /* hmac.h */; };
+ 1059009F1DC8E1FF00FB4085 /* sha2.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059005D1DC8DE3800FB4085 /* sha2.h */; };
+ 105900A11DC8E1FF00FB4085 /* tassert.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900301DC8D3DF00FB4085 /* tassert.h */; };
+ 105900A21DC8E20D00FB4085 /* openssl.h in Headers */ = {isa = PBXBuildFile; fileRef = 106530ED1D9CEFF7005B2C60 /* openssl.h */; };
+ 105900A41DC8E23B00FB4085 /* libpicotls-openssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1059008C1DC8E1A300FB4085 /* libpicotls-openssl.a */; };
+ 105900AE1DC941D700FB4085 /* gf128.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900AB1DC941D700FB4085 /* gf128.h */; };
+ 105900B21DC9438200FB4085 /* modes.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900B01DC9438200FB4085 /* modes.h */; };
+ 105900B31DC9439800FB4085 /* modes.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900AF1DC9438200FB4085 /* modes.c */; };
+ 105900B41DC943B500FB4085 /* gf128.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900AA1DC941D700FB4085 /* gf128.c */; };
+ 105900B51DC943B900FB4085 /* gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900A91DC941D700FB4085 /* gcm.c */; };
+ 105900B61DC943D400FB4085 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900241DC8D37500FB4085 /* aes.c */; };
+ 105900BE1DC96A3500FB4085 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900BA1DC96A3500FB4085 /* types.h */; };
+ 105900BF1DC96A3500FB4085 /* uECC_vli.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900BB1DC96A3500FB4085 /* uECC_vli.h */; };
+ 105900C11DC96A3500FB4085 /* uECC.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900BD1DC96A3500FB4085 /* uECC.h */; };
+ 105900C41DC96B2200FB4085 /* uECC.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900BC1DC96A3500FB4085 /* uECC.c */; };
+ 105900C71DCBECD800FB4085 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900241DC8D37500FB4085 /* aes.c */; };
+ 105900C81DCBECDD00FB4085 /* blockwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900291DC8D39800FB4085 /* blockwise.c */; };
+ 105900C91DCBECE100FB4085 /* chash.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059006B1DC8E00400FB4085 /* chash.c */; };
+ 105900CA1DCBECE500FB4085 /* curve25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900391DC8D46A00FB4085 /* curve25519.c */; };
+ 105900CB1DCBECEA00FB4085 /* drbg.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900511DC8D79300FB4085 /* drbg.c */; };
+ 105900CC1DCBECF100FB4085 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900651DC8DFD300FB4085 /* hmac.c */; };
+ 105900CD1DCBECF400FB4085 /* gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900A91DC941D700FB4085 /* gcm.c */; };
+ 105900CE1DCBECF700FB4085 /* gf128.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900AA1DC941D700FB4085 /* gf128.c */; };
+ 105900CF1DCBECFB00FB4085 /* modes.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900AF1DC9438200FB4085 /* modes.c */; };
+ 105900D01DCBECFE00FB4085 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059005F1DC8DE4400FB4085 /* sha256.c */; };
+ 105900D11DCBED0600FB4085 /* cifra.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059003F1DC8D53200FB4085 /* cifra.c */; };
+ 105900D21DCBED0A00FB4085 /* uecc.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900C51DC9798800FB4085 /* uecc.c */; };
+ 105900D31DCBED1D00FB4085 /* uECC.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900BC1DC96A3500FB4085 /* uECC.c */; };
+ 106530E51D9B4021005B2C60 /* picotest.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530E31D9B4021005B2C60 /* picotest.c */; };
+ 106530EA1D9B7C13005B2C60 /* picotls.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530E91D9B7C13005B2C60 /* picotls.c */; };
+ 106530EB1D9B7C5C005B2C60 /* picotls.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530BF1D998641005B2C60 /* picotls.c */; };
+ 106530FF1DAD8A3C005B2C60 /* cli.c in Sources */ = {isa = PBXBuildFile; fileRef = 106530FE1DAD8A3C005B2C60 /* cli.c */; };
+ 10EACAF01DCC843A00CA0341 /* drbg.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900511DC8D79300FB4085 /* drbg.c */; };
+ 10EACAF31DCEAF0F00CA0341 /* uECC.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900BC1DC96A3500FB4085 /* uECC.c */; };
+ 10EACAF41DCEAF0F00CA0341 /* uecc.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900C51DC9798800FB4085 /* uecc.c */; };
+ 10EACAF51DCEAF0F00CA0341 /* gf128.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900AA1DC941D700FB4085 /* gf128.c */; };
+ 10EACAF61DCEAF0F00CA0341 /* gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900A91DC941D700FB4085 /* gcm.c */; };
+ 10EACAF71DCEAF0F00CA0341 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059005F1DC8DE4400FB4085 /* sha256.c */; };
+ 10EACAF81DCEAF0F00CA0341 /* aes.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900241DC8D37500FB4085 /* aes.c */; };
+ 10EACAF91DCEAF0F00CA0341 /* modes.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900AF1DC9438200FB4085 /* modes.c */; };
+ 10EACAFB1DCEAF0F00CA0341 /* chash.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059006B1DC8E00400FB4085 /* chash.c */; };
+ 10EACAFC1DCEAF0F00CA0341 /* curve25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900391DC8D46A00FB4085 /* curve25519.c */; };
+ 10EACAFD1DCEAF0F00CA0341 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900651DC8DFD300FB4085 /* hmac.c */; };
+ 10EACAFE1DCEAF0F00CA0341 /* drbg.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900511DC8D79300FB4085 /* drbg.c */; };
+ 10EACAFF1DCEAF0F00CA0341 /* cifra.c in Sources */ = {isa = PBXBuildFile; fileRef = 1059003F1DC8D53200FB4085 /* cifra.c */; };
+ 10EACB001DCEAF0F00CA0341 /* blockwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 105900291DC8D39800FB4085 /* blockwise.c */; };
+ 10EACB031DCEAF0F00CA0341 /* blockwise.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059002A1DC8D39800FB4085 /* blockwise.h */; };
+ 10EACB041DCEAF0F00CA0341 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900BA1DC96A3500FB4085 /* types.h */; };
+ 10EACB051DCEAF0F00CA0341 /* uECC_vli.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900BB1DC96A3500FB4085 /* uECC_vli.h */; };
+ 10EACB061DCEAF0F00CA0341 /* modes.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900B01DC9438200FB4085 /* modes.h */; };
+ 10EACB071DCEAF0F00CA0341 /* bitops.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900281DC8D39800FB4085 /* bitops.h */; };
+ 10EACB081DCEAF0F00CA0341 /* cf_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900321DC8D41A00FB4085 /* cf_config.h */; };
+ 10EACB091DCEAF0F00CA0341 /* handy.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059002B1DC8D39800FB4085 /* handy.h */; };
+ 10EACB0A1DCEAF0F00CA0341 /* uECC.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900BD1DC96A3500FB4085 /* uECC.h */; };
+ 10EACB0B1DCEAF0F00CA0341 /* drbg.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900521DC8D79300FB4085 /* drbg.h */; };
+ 10EACB0C1DCEAF0F00CA0341 /* tassert.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900301DC8D3DF00FB4085 /* tassert.h */; };
+ 10EACB0D1DCEAF0F00CA0341 /* hmac.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900661DC8DFD300FB4085 /* hmac.h */; };
+ 10EACB0E1DCEAF0F00CA0341 /* chash.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059006C1DC8E00400FB4085 /* chash.h */; };
+ 10EACB0F1DCEAF0F00CA0341 /* sha2.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059005D1DC8DE3800FB4085 /* sha2.h */; };
+ 10EACB101DCEAF0F00CA0341 /* aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900251DC8D37500FB4085 /* aes.h */; };
+ 10EACB111DCEAF0F00CA0341 /* minicrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 1059004F1DC8D64E00FB4085 /* minicrypto.h */; };
+ 10EACB121DCEAF0F00CA0341 /* gf128.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900AB1DC941D700FB4085 /* gf128.h */; };
+ 10EACB131DCEAF0F00CA0341 /* curve25519.h in Headers */ = {isa = PBXBuildFile; fileRef = 105900361DC8D44E00FB4085 /* curve25519.h */; };
+ 10EACB1A1DCEC2A300CA0341 /* libpicotls-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 106530DA1D9B3E6F005B2C60 /* libpicotls-core.a */; };
+ E949EF282073629300511ECA /* minicrypto-pem.c in Sources */ = {isa = PBXBuildFile; fileRef = E949EF272073629300511ECA /* minicrypto-pem.c */; };
+ E99B75E01F5CDDB500CF503E /* asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = E99B75DE1F5CDDB500CF503E /* asn1.c */; };
+ E99B75E11F5CDDB500CF503E /* pembase64.c in Sources */ = {isa = PBXBuildFile; fileRef = E99B75DF1F5CDDB500CF503E /* pembase64.c */; };
+ E99B75E21F5CE54D00CF503E /* asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = E99B75DE1F5CDDB500CF503E /* asn1.c */; };
+ E99B75E31F5CE54D00CF503E /* asn1.c in Sources */ = {isa = PBXBuildFile; fileRef = E99B75DE1F5CDDB500CF503E /* asn1.c */; };
+ E99B75E41F5CE64E00CF503E /* pembase64.c in Sources */ = {isa = PBXBuildFile; fileRef = E99B75DF1F5CDDB500CF503E /* pembase64.c */; };
+ E99B75E51F5CE64E00CF503E /* pembase64.c in Sources */ = {isa = PBXBuildFile; fileRef = E99B75DF1F5CDDB500CF503E /* pembase64.c */; };
+ E9BC76CF1EF3A35E00EB7A09 /* chacha20.c in Sources */ = {isa = PBXBuildFile; fileRef = E9BC76C61EF3A2F700EB7A09 /* chacha20.c */; };
+ E9BC76D21EF3A36A00EB7A09 /* chacha20.c in Sources */ = {isa = PBXBuildFile; fileRef = E9BC76C61EF3A2F700EB7A09 /* chacha20.c */; };
+ E9BC76D41EF3A37200EB7A09 /* chacha20.c in Sources */ = {isa = PBXBuildFile; fileRef = E9BC76C61EF3A2F700EB7A09 /* chacha20.c */; };
+ E9BC76DD1EF3CCD100EB7A09 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = E9BC76D61EF3C1C200EB7A09 /* poly1305.c */; };
+ E9BC76DE1EF3CCD100EB7A09 /* poly1305.h in Headers */ = {isa = PBXBuildFile; fileRef = E9BC76D71EF3C1C200EB7A09 /* poly1305.h */; };
+ E9BC76DF1EF3CCD100EB7A09 /* salsa20.h in Headers */ = {isa = PBXBuildFile; fileRef = E9BC76CC1EF3A31000EB7A09 /* salsa20.h */; };
+ E9BC76E01EF3CCDD00EB7A09 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = E9BC76D61EF3C1C200EB7A09 /* poly1305.c */; };
+ E9BC76E11EF3CCDE00EB7A09 /* poly1305.c in Sources */ = {isa = PBXBuildFile; fileRef = E9BC76D61EF3C1C200EB7A09 /* poly1305.c */; };
+ E9E865EB203BD46600E2FFCD /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = E9E865E9203BD45600E2FFCD /* sha512.c */; };
+ E9E865EC203BD46600E2FFCD /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = E9E865E9203BD45600E2FFCD /* sha512.c */; };
+ E9E865ED203BD46700E2FFCD /* sha512.c in Sources */ = {isa = PBXBuildFile; fileRef = E9E865E9203BD45600E2FFCD /* sha512.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 105900A71DC8E2E100FB4085 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 106530AA1D9985E0005B2C60 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 105900701DC8E1A300FB4085;
+ remoteInfo = "picotls-openssl";
+ };
+ 10EACB181DCEAF4A00CA0341 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 106530AA1D9985E0005B2C60 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 106530D91D9B3E6F005B2C60;
+ remoteInfo = "picotls-core";
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 105900471DC8D57000FB4085 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 106530CA1D9B3D45005B2C60 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 106530F81DAD8985005B2C60 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 105900241DC8D37500FB4085 /* aes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = aes.c; path = src/aes.c; sourceTree = "<group>"; };
+ 105900251DC8D37500FB4085 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aes.h; path = src/aes.h; sourceTree = "<group>"; };
+ 105900281DC8D39800FB4085 /* bitops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bitops.h; path = src/bitops.h; sourceTree = "<group>"; };
+ 105900291DC8D39800FB4085 /* blockwise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = blockwise.c; path = src/blockwise.c; sourceTree = "<group>"; };
+ 1059002A1DC8D39800FB4085 /* blockwise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = blockwise.h; path = src/blockwise.h; sourceTree = "<group>"; };
+ 1059002B1DC8D39800FB4085 /* handy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = handy.h; path = src/ext/handy.h; sourceTree = "<group>"; };
+ 105900301DC8D3DF00FB4085 /* tassert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tassert.h; path = src/tassert.h; sourceTree = "<group>"; };
+ 105900321DC8D41A00FB4085 /* cf_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cf_config.h; path = src/cf_config.h; sourceTree = "<group>"; };
+ 105900361DC8D44E00FB4085 /* curve25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = curve25519.h; path = src/curve25519.h; sourceTree = "<group>"; };
+ 105900391DC8D46A00FB4085 /* curve25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = curve25519.c; path = src/curve25519.c; sourceTree = "<group>"; };
+ 1059003B1DC8D49E00FB4085 /* curve25519.tweetnacl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = curve25519.tweetnacl.c; path = src/curve25519.tweetnacl.c; sourceTree = "<group>"; };
+ 1059003D1DC8D4E300FB4085 /* minicrypto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = minicrypto.c; sourceTree = "<group>"; };
+ 1059003F1DC8D53200FB4085 /* cifra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cifra.c; sourceTree = "<group>"; };
+ 1059004B1DC8D57000FB4085 /* test-minicrypto */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "test-minicrypto"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1059004F1DC8D64E00FB4085 /* minicrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = minicrypto.h; sourceTree = "<group>"; };
+ 105900511DC8D79300FB4085 /* drbg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = drbg.c; path = src/drbg.c; sourceTree = "<group>"; };
+ 105900521DC8D79300FB4085 /* drbg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = drbg.h; path = src/drbg.h; sourceTree = "<group>"; };
+ 1059005D1DC8DE3800FB4085 /* sha2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sha2.h; path = src/sha2.h; sourceTree = "<group>"; };
+ 1059005F1DC8DE4400FB4085 /* sha256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sha256.c; path = src/sha256.c; sourceTree = "<group>"; };
+ 105900651DC8DFD300FB4085 /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hmac.c; path = src/hmac.c; sourceTree = "<group>"; };
+ 105900661DC8DFD300FB4085 /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hmac.h; path = src/hmac.h; sourceTree = "<group>"; };
+ 1059006B1DC8E00400FB4085 /* chash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = chash.c; path = src/chash.c; sourceTree = "<group>"; };
+ 1059006C1DC8E00400FB4085 /* chash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = chash.h; path = src/chash.h; sourceTree = "<group>"; };
+ 1059008C1DC8E1A300FB4085 /* libpicotls-openssl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libpicotls-openssl.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 105900A91DC941D700FB4085 /* gcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gcm.c; path = src/gcm.c; sourceTree = "<group>"; };
+ 105900AA1DC941D700FB4085 /* gf128.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gf128.c; path = src/gf128.c; sourceTree = "<group>"; };
+ 105900AB1DC941D700FB4085 /* gf128.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gf128.h; path = src/gf128.h; sourceTree = "<group>"; };
+ 105900AF1DC9438200FB4085 /* modes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = modes.c; path = src/modes.c; sourceTree = "<group>"; };
+ 105900B01DC9438200FB4085 /* modes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = modes.h; path = src/modes.h; sourceTree = "<group>"; };
+ 105900BA1DC96A3500FB4085 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
+ 105900BB1DC96A3500FB4085 /* uECC_vli.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uECC_vli.h; sourceTree = "<group>"; };
+ 105900BC1DC96A3500FB4085 /* uECC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uECC.c; sourceTree = "<group>"; };
+ 105900BD1DC96A3500FB4085 /* uECC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uECC.h; sourceTree = "<group>"; };
+ 105900C51DC9798800FB4085 /* uecc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uecc.c; sourceTree = "<group>"; };
+ 106530BE1D99863B005B2C60 /* picotls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = picotls.h; sourceTree = "<group>"; };
+ 106530BF1D998641005B2C60 /* picotls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = picotls.c; sourceTree = "<group>"; };
+ 106530C21D9B004B005B2C60 /* openssl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = openssl.c; sourceTree = "<group>"; };
+ 106530C51D9B1A98005B2C60 /* openssl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = openssl.c; sourceTree = "<group>"; };
+ 106530CC1D9B3D45005B2C60 /* test-openssl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "test-openssl"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 106530DA1D9B3E6F005B2C60 /* libpicotls-core.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libpicotls-core.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 106530E31D9B4021005B2C60 /* picotest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = picotest.c; sourceTree = "<group>"; };
+ 106530E41D9B4021005B2C60 /* picotest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = picotest.h; sourceTree = "<group>"; };
+ 106530E61D9B7AF6005B2C60 /* test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = test.h; sourceTree = "<group>"; };
+ 106530E91D9B7C13005B2C60 /* picotls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = picotls.c; sourceTree = "<group>"; };
+ 106530ED1D9CEFF7005B2C60 /* openssl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = openssl.h; path = include/picotls/openssl.h; sourceTree = SOURCE_ROOT; };
+ 106530FC1DAD8985005B2C60 /* cli */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cli; sourceTree = BUILT_PRODUCTS_DIR; };
+ 106530FE1DAD8A3C005B2C60 /* cli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cli.c; sourceTree = "<group>"; };
+ 10EACB171DCEAF0F00CA0341 /* libpicotls-minicrypto.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libpicotls-minicrypto.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ E949EF272073629300511ECA /* minicrypto-pem.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "minicrypto-pem.c"; sourceTree = "<group>"; };
+ E99B75DE1F5CDDB500CF503E /* asn1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asn1.c; sourceTree = "<group>"; };
+ E99B75DF1F5CDDB500CF503E /* pembase64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pembase64.c; sourceTree = "<group>"; };
+ E9BC76C61EF3A2F700EB7A09 /* chacha20.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = chacha20.c; path = src/chacha20.c; sourceTree = "<group>"; };
+ E9BC76CC1EF3A31000EB7A09 /* salsa20.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = salsa20.h; path = src/salsa20.h; sourceTree = "<group>"; };
+ E9BC76D61EF3C1C200EB7A09 /* poly1305.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = poly1305.c; path = src/poly1305.c; sourceTree = "<group>"; };
+ E9BC76D71EF3C1C200EB7A09 /* poly1305.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = poly1305.h; path = src/poly1305.h; sourceTree = "<group>"; };
+ E9E3849C1F0748DD00D50990 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; };
+ E9E865E9203BD45600E2FFCD /* sha512.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sha512.c; path = src/sha512.c; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 105900461DC8D57000FB4085 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 1059007B1DC8E1A300FB4085 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530C91D9B3D45005B2C60 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530D71D9B3E6F005B2C60 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530F71DAD8985005B2C60 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 105900A41DC8E23B00FB4085 /* libpicotls-openssl.a in Frameworks */,
+ 10EACB1A1DCEC2A300CA0341 /* libpicotls-core.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 10EACB011DCEAF0F00CA0341 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 105900231DC8D34400FB4085 /* cifra */ = {
+ isa = PBXGroup;
+ children = (
+ 105900251DC8D37500FB4085 /* aes.h */,
+ 105900241DC8D37500FB4085 /* aes.c */,
+ 105900281DC8D39800FB4085 /* bitops.h */,
+ 1059002A1DC8D39800FB4085 /* blockwise.h */,
+ 105900291DC8D39800FB4085 /* blockwise.c */,
+ E9BC76C61EF3A2F700EB7A09 /* chacha20.c */,
+ 1059006C1DC8E00400FB4085 /* chash.h */,
+ 1059006B1DC8E00400FB4085 /* chash.c */,
+ 105900361DC8D44E00FB4085 /* curve25519.h */,
+ 105900391DC8D46A00FB4085 /* curve25519.c */,
+ 1059003B1DC8D49E00FB4085 /* curve25519.tweetnacl.c */,
+ 105900321DC8D41A00FB4085 /* cf_config.h */,
+ 105900521DC8D79300FB4085 /* drbg.h */,
+ 105900511DC8D79300FB4085 /* drbg.c */,
+ 1059002B1DC8D39800FB4085 /* handy.h */,
+ 105900661DC8DFD300FB4085 /* hmac.h */,
+ 105900651DC8DFD300FB4085 /* hmac.c */,
+ 105900A91DC941D700FB4085 /* gcm.c */,
+ 105900AB1DC941D700FB4085 /* gf128.h */,
+ 105900AA1DC941D700FB4085 /* gf128.c */,
+ 105900B01DC9438200FB4085 /* modes.h */,
+ 105900AF1DC9438200FB4085 /* modes.c */,
+ E9BC76D71EF3C1C200EB7A09 /* poly1305.h */,
+ E9BC76D61EF3C1C200EB7A09 /* poly1305.c */,
+ E9BC76CC1EF3A31000EB7A09 /* salsa20.h */,
+ 1059005D1DC8DE3800FB4085 /* sha2.h */,
+ 1059005F1DC8DE4400FB4085 /* sha256.c */,
+ E9E865E9203BD45600E2FFCD /* sha512.c */,
+ 105900301DC8D3DF00FB4085 /* tassert.h */,
+ );
+ path = cifra;
+ sourceTree = "<group>";
+ };
+ 105900B91DC96A1B00FB4085 /* micro-ecc */ = {
+ isa = PBXGroup;
+ children = (
+ 105900BA1DC96A3500FB4085 /* types.h */,
+ 105900BD1DC96A3500FB4085 /* uECC.h */,
+ 105900BB1DC96A3500FB4085 /* uECC_vli.h */,
+ 105900BC1DC96A3500FB4085 /* uECC.c */,
+ );
+ path = "micro-ecc";
+ sourceTree = "<group>";
+ };
+ 106530A91D9985E0005B2C60 = {
+ isa = PBXGroup;
+ children = (
+ 106530E11D9B4000005B2C60 /* deps */,
+ 106530BC1D998616005B2C60 /* include */,
+ 106530BD1D998624005B2C60 /* lib */,
+ 106530C41D9B1A0E005B2C60 /* t */,
+ 106530B31D9985E0005B2C60 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 106530B31D9985E0005B2C60 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 106530CC1D9B3D45005B2C60 /* test-openssl */,
+ 106530DA1D9B3E6F005B2C60 /* libpicotls-core.a */,
+ 106530FC1DAD8985005B2C60 /* cli */,
+ 1059004B1DC8D57000FB4085 /* test-minicrypto */,
+ 1059008C1DC8E1A300FB4085 /* libpicotls-openssl.a */,
+ 10EACB171DCEAF0F00CA0341 /* libpicotls-minicrypto.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 106530BC1D998616005B2C60 /* include */ = {
+ isa = PBXGroup;
+ children = (
+ 106530EE1D9E3476005B2C60 /* picotls */,
+ 106530BE1D99863B005B2C60 /* picotls.h */,
+ );
+ path = include;
+ sourceTree = "<group>";
+ };
+ 106530BD1D998624005B2C60 /* lib */ = {
+ isa = PBXGroup;
+ children = (
+ E99B75DE1F5CDDB500CF503E /* asn1.c */,
+ E99B75DF1F5CDDB500CF503E /* pembase64.c */,
+ 1059003F1DC8D53200FB4085 /* cifra.c */,
+ 106530C21D9B004B005B2C60 /* openssl.c */,
+ 106530BF1D998641005B2C60 /* picotls.c */,
+ 105900C51DC9798800FB4085 /* uecc.c */,
+ E949EF272073629300511ECA /* minicrypto-pem.c */,
+ );
+ path = lib;
+ sourceTree = "<group>";
+ };
+ 106530C41D9B1A0E005B2C60 /* t */ = {
+ isa = PBXGroup;
+ children = (
+ 106530FE1DAD8A3C005B2C60 /* cli.c */,
+ 106530E91D9B7C13005B2C60 /* picotls.c */,
+ 1059003D1DC8D4E300FB4085 /* minicrypto.c */,
+ 106530C51D9B1A98005B2C60 /* openssl.c */,
+ 106530E61D9B7AF6005B2C60 /* test.h */,
+ E9E3849C1F0748DD00D50990 /* util.h */,
+ );
+ path = t;
+ sourceTree = "<group>";
+ };
+ 106530E11D9B4000005B2C60 /* deps */ = {
+ isa = PBXGroup;
+ children = (
+ 105900B91DC96A1B00FB4085 /* micro-ecc */,
+ 105900231DC8D34400FB4085 /* cifra */,
+ 106530E21D9B4005005B2C60 /* picotest */,
+ );
+ path = deps;
+ sourceTree = "<group>";
+ };
+ 106530E21D9B4005005B2C60 /* picotest */ = {
+ isa = PBXGroup;
+ children = (
+ 106530E41D9B4021005B2C60 /* picotest.h */,
+ 106530E31D9B4021005B2C60 /* picotest.c */,
+ );
+ path = picotest;
+ sourceTree = "<group>";
+ };
+ 106530EE1D9E3476005B2C60 /* picotls */ = {
+ isa = PBXGroup;
+ children = (
+ 1059004F1DC8D64E00FB4085 /* minicrypto.h */,
+ 106530ED1D9CEFF7005B2C60 /* openssl.h */,
+ );
+ path = picotls;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 1059007C1DC8E1A300FB4085 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 105900A21DC8E20D00FB4085 /* openssl.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530D81D9B3E6F005B2C60 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 105900921DC8E1FF00FB4085 /* blockwise.h in Headers */,
+ 105900BE1DC96A3500FB4085 /* types.h in Headers */,
+ 105900BF1DC96A3500FB4085 /* uECC_vli.h in Headers */,
+ 105900B21DC9438200FB4085 /* modes.h in Headers */,
+ 105900911DC8E1FF00FB4085 /* bitops.h in Headers */,
+ 105900991DC8E1FF00FB4085 /* cf_config.h in Headers */,
+ 1059009C1DC8E1FF00FB4085 /* handy.h in Headers */,
+ 105900C11DC96A3500FB4085 /* uECC.h in Headers */,
+ 1059009A1DC8E1FF00FB4085 /* drbg.h in Headers */,
+ 105900A11DC8E1FF00FB4085 /* tassert.h in Headers */,
+ 1059009D1DC8E1FF00FB4085 /* hmac.h in Headers */,
+ 105900941DC8E1FF00FB4085 /* chash.h in Headers */,
+ 1059009F1DC8E1FF00FB4085 /* sha2.h in Headers */,
+ 1059008F1DC8E1FF00FB4085 /* aes.h in Headers */,
+ 105900501DC8D64E00FB4085 /* minicrypto.h in Headers */,
+ 105900AE1DC941D700FB4085 /* gf128.h in Headers */,
+ 105900961DC8E1FF00FB4085 /* curve25519.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 10EACB021DCEAF0F00CA0341 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 10EACB031DCEAF0F00CA0341 /* blockwise.h in Headers */,
+ 10EACB041DCEAF0F00CA0341 /* types.h in Headers */,
+ 10EACB051DCEAF0F00CA0341 /* uECC_vli.h in Headers */,
+ 10EACB061DCEAF0F00CA0341 /* modes.h in Headers */,
+ E9BC76DF1EF3CCD100EB7A09 /* salsa20.h in Headers */,
+ 10EACB071DCEAF0F00CA0341 /* bitops.h in Headers */,
+ 10EACB081DCEAF0F00CA0341 /* cf_config.h in Headers */,
+ 10EACB091DCEAF0F00CA0341 /* handy.h in Headers */,
+ 10EACB0A1DCEAF0F00CA0341 /* uECC.h in Headers */,
+ 10EACB0B1DCEAF0F00CA0341 /* drbg.h in Headers */,
+ 10EACB0C1DCEAF0F00CA0341 /* tassert.h in Headers */,
+ 10EACB0D1DCEAF0F00CA0341 /* hmac.h in Headers */,
+ 10EACB0E1DCEAF0F00CA0341 /* chash.h in Headers */,
+ 10EACB0F1DCEAF0F00CA0341 /* sha2.h in Headers */,
+ E9BC76DE1EF3CCD100EB7A09 /* poly1305.h in Headers */,
+ 10EACB101DCEAF0F00CA0341 /* aes.h in Headers */,
+ 10EACB111DCEAF0F00CA0341 /* minicrypto.h in Headers */,
+ 10EACB121DCEAF0F00CA0341 /* gf128.h in Headers */,
+ 10EACB131DCEAF0F00CA0341 /* curve25519.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 105900411DC8D57000FB4085 /* test-minicrypto */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 105900481DC8D57000FB4085 /* Build configuration list for PBXNativeTarget "test-minicrypto" */;
+ buildPhases = (
+ 105900421DC8D57000FB4085 /* Sources */,
+ 105900461DC8D57000FB4085 /* Frameworks */,
+ 105900471DC8D57000FB4085 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "test-minicrypto";
+ productName = "test-crypto-openssl";
+ productReference = 1059004B1DC8D57000FB4085 /* test-minicrypto */;
+ productType = "com.apple.product-type.tool";
+ };
+ 105900701DC8E1A300FB4085 /* picotls-openssl */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 105900891DC8E1A300FB4085 /* Build configuration list for PBXNativeTarget "picotls-openssl" */;
+ buildPhases = (
+ 105900711DC8E1A300FB4085 /* Sources */,
+ 1059007B1DC8E1A300FB4085 /* Frameworks */,
+ 1059007C1DC8E1A300FB4085 /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "picotls-openssl";
+ productName = picotls;
+ productReference = 1059008C1DC8E1A300FB4085 /* libpicotls-openssl.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 106530CB1D9B3D45005B2C60 /* test-openssl */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 106530D01D9B3D45005B2C60 /* Build configuration list for PBXNativeTarget "test-openssl" */;
+ buildPhases = (
+ 106530C81D9B3D45005B2C60 /* Sources */,
+ 106530C91D9B3D45005B2C60 /* Frameworks */,
+ 106530CA1D9B3D45005B2C60 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "test-openssl";
+ productName = "test-crypto-openssl";
+ productReference = 106530CC1D9B3D45005B2C60 /* test-openssl */;
+ productType = "com.apple.product-type.tool";
+ };
+ 106530D91D9B3E6F005B2C60 /* picotls-core */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 106530DD1D9B3E6F005B2C60 /* Build configuration list for PBXNativeTarget "picotls-core" */;
+ buildPhases = (
+ 106530D61D9B3E6F005B2C60 /* Sources */,
+ 106530D71D9B3E6F005B2C60 /* Frameworks */,
+ 106530D81D9B3E6F005B2C60 /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "picotls-core";
+ productName = picotls;
+ productReference = 106530DA1D9B3E6F005B2C60 /* libpicotls-core.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 106530F11DAD8985005B2C60 /* cli */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 106530F91DAD8985005B2C60 /* Build configuration list for PBXNativeTarget "cli" */;
+ buildPhases = (
+ 106530F21DAD8985005B2C60 /* Sources */,
+ 106530F71DAD8985005B2C60 /* Frameworks */,
+ 106530F81DAD8985005B2C60 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 10EACB191DCEAF4A00CA0341 /* PBXTargetDependency */,
+ 105900A81DC8E2E100FB4085 /* PBXTargetDependency */,
+ );
+ name = cli;
+ productName = "test-crypto-openssl";
+ productReference = 106530FC1DAD8985005B2C60 /* cli */;
+ productType = "com.apple.product-type.tool";
+ };
+ 10EACAF11DCEAF0F00CA0341 /* picotls-minicrypto */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 10EACB141DCEAF0F00CA0341 /* Build configuration list for PBXNativeTarget "picotls-minicrypto" */;
+ buildPhases = (
+ 10EACAF21DCEAF0F00CA0341 /* Sources */,
+ 10EACB011DCEAF0F00CA0341 /* Frameworks */,
+ 10EACB021DCEAF0F00CA0341 /* Headers */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "picotls-minicrypto";
+ productName = picotls;
+ productReference = 10EACB171DCEAF0F00CA0341 /* libpicotls-minicrypto.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 106530AA1D9985E0005B2C60 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0830;
+ ORGANIZATIONNAME = "DeNA Co., Ltd.";
+ TargetAttributes = {
+ 106530CB1D9B3D45005B2C60 = {
+ CreatedOnToolsVersion = 7.3.1;
+ };
+ 106530D91D9B3E6F005B2C60 = {
+ CreatedOnToolsVersion = 7.3.1;
+ };
+ };
+ };
+ buildConfigurationList = 106530AD1D9985E0005B2C60 /* Build configuration list for PBXProject "picotls" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 106530A91D9985E0005B2C60;
+ productRefGroup = 106530B31D9985E0005B2C60 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 106530D91D9B3E6F005B2C60 /* picotls-core */,
+ 10EACAF11DCEAF0F00CA0341 /* picotls-minicrypto */,
+ 105900701DC8E1A300FB4085 /* picotls-openssl */,
+ 106530F11DAD8985005B2C60 /* cli */,
+ 106530CB1D9B3D45005B2C60 /* test-openssl */,
+ 105900411DC8D57000FB4085 /* test-minicrypto */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 105900421DC8D57000FB4085 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 105900B61DC943D400FB4085 /* aes.c in Sources */,
+ E99B75E51F5CE64E00CF503E /* pembase64.c in Sources */,
+ 105900431DC8D57000FB4085 /* picotls.c in Sources */,
+ 105900C41DC96B2200FB4085 /* uECC.c in Sources */,
+ 105900441DC8D57000FB4085 /* picotest.c in Sources */,
+ 105900611DC8DF8C00FB4085 /* sha256.c in Sources */,
+ E9BC76D21EF3A36A00EB7A09 /* chacha20.c in Sources */,
+ 1059004E1DC8D61800FB4085 /* minicrypto.c in Sources */,
+ E99B75E31F5CE54D00CF503E /* asn1.c in Sources */,
+ E9E865ED203BD46700E2FFCD /* sha512.c in Sources */,
+ 10EACAF01DCC843A00CA0341 /* drbg.c in Sources */,
+ E9BC76E11EF3CCDE00EB7A09 /* poly1305.c in Sources */,
+ 1059006A1DC8DFE300FB4085 /* hmac.c in Sources */,
+ 1059006F1DC8E00B00FB4085 /* chash.c in Sources */,
+ 105900B41DC943B500FB4085 /* gf128.c in Sources */,
+ 105900641DC8DFA700FB4085 /* curve25519.c in Sources */,
+ 105900B51DC943B900FB4085 /* gcm.c in Sources */,
+ 105900B31DC9439800FB4085 /* modes.c in Sources */,
+ 105900691DC8DFDF00FB4085 /* blockwise.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 105900711DC8E1A300FB4085 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 105900761DC8E1A300FB4085 /* openssl.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530C81D9B3D45005B2C60 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E9BC76E01EF3CCDD00EB7A09 /* poly1305.c in Sources */,
+ 105900CF1DCBECFB00FB4085 /* modes.c in Sources */,
+ 106530EA1D9B7C13005B2C60 /* picotls.c in Sources */,
+ 105900CD1DCBECF400FB4085 /* gcm.c in Sources */,
+ E9E865EC203BD46600E2FFCD /* sha512.c in Sources */,
+ 105900D01DCBECFE00FB4085 /* sha256.c in Sources */,
+ 1059004C1DC8D5B700FB4085 /* openssl.c in Sources */,
+ 105900D21DCBED0A00FB4085 /* uecc.c in Sources */,
+ E99B75E21F5CE54D00CF503E /* asn1.c in Sources */,
+ 105900C81DCBECDD00FB4085 /* blockwise.c in Sources */,
+ 105900D31DCBED1D00FB4085 /* uECC.c in Sources */,
+ 105900C91DCBECE100FB4085 /* chash.c in Sources */,
+ 106530E51D9B4021005B2C60 /* picotest.c in Sources */,
+ 105900C71DCBECD800FB4085 /* aes.c in Sources */,
+ 105900D11DCBED0600FB4085 /* cifra.c in Sources */,
+ 105900CE1DCBECF700FB4085 /* gf128.c in Sources */,
+ 105900CC1DCBECF100FB4085 /* hmac.c in Sources */,
+ E9BC76D41EF3A37200EB7A09 /* chacha20.c in Sources */,
+ 105900CB1DCBECEA00FB4085 /* drbg.c in Sources */,
+ 105900CA1DCBECE500FB4085 /* curve25519.c in Sources */,
+ E99B75E41F5CE64E00CF503E /* pembase64.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530D61D9B3E6F005B2C60 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E99B75E01F5CDDB500CF503E /* asn1.c in Sources */,
+ E99B75E11F5CDDB500CF503E /* pembase64.c in Sources */,
+ 106530EB1D9B7C5C005B2C60 /* picotls.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 106530F21DAD8985005B2C60 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 106530FF1DAD8A3C005B2C60 /* cli.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 10EACAF21DCEAF0F00CA0341 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 10EACAF31DCEAF0F00CA0341 /* uECC.c in Sources */,
+ 10EACAF41DCEAF0F00CA0341 /* uecc.c in Sources */,
+ E949EF282073629300511ECA /* minicrypto-pem.c in Sources */,
+ 10EACAF51DCEAF0F00CA0341 /* gf128.c in Sources */,
+ 10EACAF61DCEAF0F00CA0341 /* gcm.c in Sources */,
+ 10EACAF71DCEAF0F00CA0341 /* sha256.c in Sources */,
+ 10EACAF81DCEAF0F00CA0341 /* aes.c in Sources */,
+ E9BC76DD1EF3CCD100EB7A09 /* poly1305.c in Sources */,
+ 10EACAF91DCEAF0F00CA0341 /* modes.c in Sources */,
+ E9BC76CF1EF3A35E00EB7A09 /* chacha20.c in Sources */,
+ 10EACAFB1DCEAF0F00CA0341 /* chash.c in Sources */,
+ 10EACAFC1DCEAF0F00CA0341 /* curve25519.c in Sources */,
+ 10EACAFD1DCEAF0F00CA0341 /* hmac.c in Sources */,
+ 10EACAFE1DCEAF0F00CA0341 /* drbg.c in Sources */,
+ E9E865EB203BD46600E2FFCD /* sha512.c in Sources */,
+ 10EACAFF1DCEAF0F00CA0341 /* cifra.c in Sources */,
+ 10EACB001DCEAF0F00CA0341 /* blockwise.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 105900A81DC8E2E100FB4085 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 105900701DC8E1A300FB4085 /* picotls-openssl */;
+ targetProxy = 105900A71DC8E2E100FB4085 /* PBXContainerItemProxy */;
+ };
+ 10EACB191DCEAF4A00CA0341 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 106530D91D9B3E6F005B2C60 /* picotls-core */;
+ targetProxy = 10EACB181DCEAF4A00CA0341 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 105900491DC8D57000FB4085 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 1059004A1DC8D57000FB4085 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 1059008A1DC8E1A300FB4085 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ HEADER_SEARCH_PATHS = (
+ "/usr/local/openssl-1.0.2/include",
+ include,
+ );
+ LIBRARY_SEARCH_PATHS = "/usr/local/openssl-1.0.2/lib";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 1059008B1DC8E1A300FB4085 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ HEADER_SEARCH_PATHS = (
+ "/usr/local/openssl-1.0.2/include",
+ include,
+ );
+ LIBRARY_SEARCH_PATHS = "/usr/local/openssl-1.0.2/lib";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 106530B71D9985E0005B2C60 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = include;
+ LIBRARY_SEARCH_PATHS = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 106530B81D9985E0005B2C60 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = include;
+ LIBRARY_SEARCH_PATHS = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 106530D11D9B3D45005B2C60 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ HEADER_SEARCH_PATHS = (
+ "/usr/local/openssl-1.0.2/include",
+ include,
+ );
+ LIBRARY_SEARCH_PATHS = "/usr/local/openssl-1.0.2/lib";
+ OTHER_LDFLAGS = "-lcrypto";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 106530D21D9B3D45005B2C60 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ HEADER_SEARCH_PATHS = (
+ "/usr/local/openssl-1.0.2/include",
+ include,
+ );
+ LIBRARY_SEARCH_PATHS = "/usr/local/openssl-1.0.2/lib";
+ OTHER_LDFLAGS = "-lcrypto";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 106530DB1D9B3E6F005B2C60 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 106530DC1D9B3E6F005B2C60 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 106530FA1DAD8985005B2C60 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ "/usr/local/openssl-1.0.2/include",
+ include,
+ );
+ LIBRARY_SEARCH_PATHS = "/usr/local/openssl-1.0.2/lib";
+ OTHER_LDFLAGS = "-lcrypto";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 106530FB1DAD8985005B2C60 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ "/usr/local/openssl-1.0.2/include",
+ include,
+ );
+ LIBRARY_SEARCH_PATHS = "/usr/local/openssl-1.0.2/lib";
+ OTHER_LDFLAGS = "-lcrypto";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 10EACB151DCEAF0F00CA0341 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 10EACB161DCEAF0F00CA0341 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ EXECUTABLE_PREFIX = lib;
+ GCC_PREPROCESSOR_DEFINITIONS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 105900481DC8D57000FB4085 /* Build configuration list for PBXNativeTarget "test-minicrypto" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 105900491DC8D57000FB4085 /* Debug */,
+ 1059004A1DC8D57000FB4085 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 105900891DC8E1A300FB4085 /* Build configuration list for PBXNativeTarget "picotls-openssl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1059008A1DC8E1A300FB4085 /* Debug */,
+ 1059008B1DC8E1A300FB4085 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 106530AD1D9985E0005B2C60 /* Build configuration list for PBXProject "picotls" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 106530B71D9985E0005B2C60 /* Debug */,
+ 106530B81D9985E0005B2C60 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 106530D01D9B3D45005B2C60 /* Build configuration list for PBXNativeTarget "test-openssl" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 106530D11D9B3D45005B2C60 /* Debug */,
+ 106530D21D9B3D45005B2C60 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 106530DD1D9B3E6F005B2C60 /* Build configuration list for PBXNativeTarget "picotls-core" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 106530DB1D9B3E6F005B2C60 /* Debug */,
+ 106530DC1D9B3E6F005B2C60 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 106530F91DAD8985005B2C60 /* Build configuration list for PBXNativeTarget "cli" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 106530FA1DAD8985005B2C60 /* Debug */,
+ 106530FB1DAD8985005B2C60 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 10EACB141DCEAF0F00CA0341 /* Build configuration list for PBXNativeTarget "picotls-minicrypto" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 10EACB151DCEAF0F00CA0341 /* Debug */,
+ 10EACB161DCEAF0F00CA0341 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 106530AA1D9985E0005B2C60 /* Project object */;
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..5cd1211d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotls.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:picotls.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/ReadMe.txt b/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/ReadMe.txt
new file mode 100644
index 00000000..c1a42b27
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/ReadMe.txt
@@ -0,0 +1,29 @@
+========================================================================
+ STATIC LIBRARY : cifra Project Overview
+========================================================================
+
+AppWizard has created this cifra library project for you.
+
+No source files were created as part of your project.
+
+
+cifra.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+cifra.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj b/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj
new file mode 100644
index 00000000..53c73cfe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>cifra</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\deps\cifra\src;$(ProjectDir)..\..\deps\cifra\src\ext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\deps\cifra\src;$(ProjectDir)..\..\deps\cifra\src\ext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\deps\cifra\src;$(ProjectDir)..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSLDIR)\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\deps\cifra\src;$(ProjectDir)..\..\deps\cifra\src\ext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\deps\cifra\src\aes.c" />
+ <ClCompile Include="..\..\deps\cifra\src\blockwise.c" />
+ <ClCompile Include="..\..\deps\cifra\src\chacha20.c" />
+ <ClCompile Include="..\..\deps\cifra\src\chacha20poly1305.c" />
+ <ClCompile Include="..\..\deps\cifra\src\chash.c" />
+ <ClCompile Include="..\..\deps\cifra\src\cmac.c" />
+ <ClCompile Include="..\..\deps\cifra\src\curve25519.c" />
+ <ClCompile Include="..\..\deps\cifra\src\drbg.c" />
+ <ClCompile Include="..\..\deps\cifra\src\eax.c" />
+ <ClCompile Include="..\..\deps\cifra\src\gcm.c" />
+ <ClCompile Include="..\..\deps\cifra\src\gf128.c" />
+ <ClCompile Include="..\..\deps\cifra\src\hmac.c" />
+ <ClCompile Include="..\..\deps\cifra\src\modes.c" />
+ <ClCompile Include="..\..\deps\cifra\src\norx.c" />
+ <ClCompile Include="..\..\deps\cifra\src\ocb.c" />
+ <ClCompile Include="..\..\deps\cifra\src\pbkdf2.c" />
+ <ClCompile Include="..\..\deps\cifra\src\poly1305.c" />
+ <ClCompile Include="..\..\deps\cifra\src\salsa20.c" />
+ <ClCompile Include="..\..\deps\cifra\src\sha1.c" />
+ <ClCompile Include="..\..\deps\cifra\src\sha256.c" />
+ <ClCompile Include="..\..\deps\cifra\src\sha512.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\deps\cifra\src\aes.h" />
+ <ClInclude Include="..\..\deps\cifra\src\bitops.h" />
+ <ClInclude Include="..\..\deps\cifra\src\blockwise.h" />
+ <ClInclude Include="..\..\deps\cifra\src\cf_config.h" />
+ <ClInclude Include="..\..\deps\cifra\src\chacha20poly1305.h" />
+ <ClInclude Include="..\..\deps\cifra\src\chash.h" />
+ <ClInclude Include="..\..\deps\cifra\src\curve25519.h" />
+ <ClInclude Include="..\..\deps\cifra\src\drbg.h" />
+ <ClInclude Include="..\..\deps\cifra\src\gf128.h" />
+ <ClInclude Include="..\..\deps\cifra\src\hmac.h" />
+ <ClInclude Include="..\..\deps\cifra\src\modes.h" />
+ <ClInclude Include="..\..\deps\cifra\src\norx.h" />
+ <ClInclude Include="..\..\deps\cifra\src\pbkdf2.h" />
+ <ClInclude Include="..\..\deps\cifra\src\poly1305.h" />
+ <ClInclude Include="..\..\deps\cifra\src\prp.h" />
+ <ClInclude Include="..\..\deps\cifra\src\salsa20.h" />
+ <ClInclude Include="..\..\deps\cifra\src\sha1.h" />
+ <ClInclude Include="..\..\deps\cifra\src\sha2.h" />
+ <ClInclude Include="..\..\deps\cifra\src\sha3.h" />
+ <ClInclude Include="..\..\deps\cifra\src\tassert.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\deps\cifra\src\poly1305.py" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj.filters b/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj.filters
new file mode 100644
index 00000000..6c0de7f3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/cifra/cifra.vcxproj.filters
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\deps\cifra\src\aes.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\blockwise.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\chacha20.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\chacha20poly1305.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\chash.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\cmac.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\drbg.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\eax.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\gcm.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\gf128.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\hmac.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\modes.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\norx.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\ocb.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\pbkdf2.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\poly1305.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\salsa20.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\sha1.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\sha256.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\sha512.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\deps\cifra\src\curve25519.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\deps\cifra\src\aes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\bitops.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\blockwise.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\cf_config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\chacha20poly1305.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\chash.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\curve25519.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\drbg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\gf128.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\hmac.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\modes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\norx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\pbkdf2.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\poly1305.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\prp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\salsa20.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\sha1.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\sha2.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\sha3.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\tassert.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\deps\cifra\src\poly1305.py" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/ReadMe.txt b/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/ReadMe.txt
new file mode 100644
index 00000000..ed0a5281
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/ReadMe.txt
@@ -0,0 +1,29 @@
+========================================================================
+ STATIC LIBRARY : microecc Project Overview
+========================================================================
+
+AppWizard has created this microecc library project for you.
+
+No source files were created as part of your project.
+
+
+microecc.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+microecc.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj b/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj
new file mode 100644
index 00000000..46ebc5b9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>microecc</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\..\picotls;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSLDIR)\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\deps\micro-ecc\uECC.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj.filters b/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj.filters
new file mode 100644
index 00000000..b7ed7be3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/microecc/microecc.vcxproj.filters
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\deps\micro-ecc\uECC.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/openssl.cnf b/web/server/h2o/libh2o/deps/picotls/picotlsvs/openssl.cnf
new file mode 100644
index 00000000..c96e8432
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/openssl.cnf
@@ -0,0 +1,35 @@
+[ req ]
+default_bits = 1024
+default_keyfile= privkey.pem
+distinguished_name = req_distinguished_name
+
+
+[ req_distinguished_name ]
+countryName= US
+countryName_min= 2
+countryName_max = 2
+stateOrProvinceName= Washington
+localityName = Seattle
+organizationName = Example
+commonName = Localhost
+commonName_max = 64
+emailAddress = localhost@example.com
+emailAddress_max = 40
+
+
+[ alternate_names ]
+
+DNS.1 = example.com
+DNS.2 = www.example.com
+DNS.3 = mail.example.com
+DNS.4 = ftp.example.com
+
+# Add these if you need them. But usually you don't want them or
+# need them in production. You may need them for development.
+# DNS.5 = localhost
+# DNS.6 = localhost.localdomain
+# DNS.7 = 127.0.0.1
+
+# IPv6 localhost
+# DNS.8 = ::1
+
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/ReadMe.txt b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/ReadMe.txt
new file mode 100644
index 00000000..08baa570
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/ReadMe.txt
@@ -0,0 +1,37 @@
+========================================================================
+ STATIC LIBRARY : picotls Project Overview
+========================================================================
+
+AppWizard has created this picotls library project for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your picotls application.
+
+
+picotls.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+picotls.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named picotls.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj
new file mode 100644
index 00000000..1eea9ea1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{46E6D6E9-7A30-4058-9661-DF70CC07E821}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>picotls</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\..\picotls;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSLDIR)\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)..\..\deps\cifra\src;$(ProjectDir)..\..\deps\micro-ecc;$(OPENSSL64DIR)\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)\..\..\picotls;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSLDIR)\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_LIB;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)..\..\include\picotls;$(ProjectDir)..\..\deps\cifra\src;$(ProjectDir)..\..\deps\micro-ecc;$(OPENSSL64DIR)\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\deps\cifra\src\aes.h" />
+ <ClInclude Include="..\..\deps\cifra\src\bitops.h" />
+ <ClInclude Include="..\..\deps\cifra\src\blockwise.h" />
+ <ClInclude Include="..\..\deps\cifra\src\cf_config.h" />
+ <ClInclude Include="..\..\deps\cifra\src\chacha20poly1305.h" />
+ <ClInclude Include="..\..\deps\cifra\src\chash.h" />
+ <ClInclude Include="..\..\deps\cifra\src\curve25519.h" />
+ <ClInclude Include="..\..\deps\cifra\src\drbg.h" />
+ <ClInclude Include="..\..\deps\cifra\src\gf128.h" />
+ <ClInclude Include="..\..\deps\cifra\src\hmac.h" />
+ <ClInclude Include="..\..\deps\cifra\src\modes.h" />
+ <ClInclude Include="..\..\deps\cifra\src\norx.h" />
+ <ClInclude Include="..\..\deps\cifra\src\pbkdf2.h" />
+ <ClInclude Include="..\..\deps\cifra\src\poly1305.h" />
+ <ClInclude Include="..\..\deps\cifra\src\prp.h" />
+ <ClInclude Include="..\..\deps\cifra\src\salsa20.h" />
+ <ClInclude Include="..\..\deps\cifra\src\sha1.h" />
+ <ClInclude Include="..\..\deps\cifra\src\sha2.h" />
+ <ClInclude Include="..\..\deps\cifra\src\sha3.h" />
+ <ClInclude Include="..\..\deps\cifra\src\tassert.h" />
+ <ClInclude Include="..\..\include\picotls\asn1.h" />
+ <ClInclude Include="..\..\include\picotls\minicrypto.h" />
+ <ClInclude Include="..\..\include\picotls\pembase64.h" />
+ <ClInclude Include="targetver.h" />
+ <ClInclude Include="wincompat.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\lib\asn1.c" />
+ <ClCompile Include="..\..\lib\pembase64.c" />
+ <ClCompile Include="..\..\lib\cifra.c" />
+ <ClCompile Include="..\..\lib\openssl.c" />
+ <ClCompile Include="..\..\lib\picotls.c" />
+ <ClCompile Include="..\..\lib\uecc.c" />
+ <ClCompile Include="wintimeofday.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\deps\cifra\src\poly1305.py" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.filters b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.filters
new file mode 100644
index 00000000..4603cc47
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.filters
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="targetver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="wincompat.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\aes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\bitops.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\blockwise.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\cf_config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\chacha20poly1305.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\chash.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\curve25519.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\drbg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\gf128.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\hmac.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\modes.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\norx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\pbkdf2.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\poly1305.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\prp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\salsa20.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\sha1.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\sha2.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\sha3.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\tassert.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\picotls\minicrypto.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\picotls\asn1.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\picotls\pembase64.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\lib\openssl.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\lib\picotls.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\lib\uecc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="wintimeofday.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\lib\cifra.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\lib\pembase64.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\lib\asn1.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\deps\cifra\src\poly1305.py" />
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.user b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.user
new file mode 100644
index 00000000..be250787
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/picotls.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/targetver.h b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/targetver.h
new file mode 100644
index 00000000..87c0086d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wincompat.h b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wincompat.h
new file mode 100644
index 00000000..8ff26bfb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wincompat.h
@@ -0,0 +1,35 @@
+#ifndef WINCOMPAT_H
+#define WINCOMPAT_H
+
+#include <stdint.h>
+#define ssize_t int
+#include <Winsock2.h>
+
+#ifndef gettimeofday
+#define gettimeofday wintimeofday
+
+#ifndef __attribute__
+#define __attribute__(X)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ struct timezone {
+ int tz_minuteswest; /* minutes west of Greenwich */
+ int tz_dsttime; /* type of DST correction */
+ };
+
+ int wintimeofday(struct timeval* tv, struct timezone* tz);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+
+
+#endif
+
+
+#endif /* WINCOMPAT_H */ \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wintimeofday.c b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wintimeofday.c
new file mode 100644
index 00000000..a293707e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotls/wintimeofday.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Christian Huitema <huitema@huitema.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef _WINDOWS
+#include "wincompat.h"
+
+ /*
+ * This is a simple replacement for the "gettimeofday" finction,
+ * which is not available on Windows
+ */
+
+int wintimeofday(struct timeval* tv, struct timezone* tz)
+{
+ FILETIME ft;
+ uint64_t now = 0;
+
+ /*
+ * The GetSystemTimeAsFileTime API returns the number
+ * of 100-nanosecond intervals since January 1, 1601 (UTC),
+ * in FILETIME format.
+ */
+ GetSystemTimeAsFileTime(&ft);
+
+ /*
+ * Convert to plain 64 bit format, without making
+ * assumptions about the FILETIME structure alignment.
+ */
+ now = ft.dwHighDateTime;
+ now <<= 32;
+ now |= ft.dwLowDateTime;
+ /*
+ * Convert units from 100ns to 1us
+ */
+ now /= 10;
+ /*
+ * Account for microseconds elapsed between 1601 and 1970.
+ */
+ now -= 11644473600000000ULL;
+
+ if (tv != NULL)
+ {
+ uint64_t sec = now / 1000000;
+ uint64_t usec = now % 1000000;
+
+ tv->tv_sec = (long)sec;
+ tv->tv_usec = (long)usec;
+ }
+
+ if (tz != NULL)
+ {
+ /*
+ * TODO: implement a timezone retrieval function.
+ * Not urgent, since the GetDNS code always set this parameter to NULL.
+ */
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* WIN32 */ \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs.sln b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs.sln
new file mode 100644
index 00000000..dd273a45
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs.sln
@@ -0,0 +1,78 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.9
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotlsvs", "picotlsvs\picotlsvs.vcxproj", "{D0265367-FCCF-47A4-95FD-C33BECAB3486}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440} = {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821} = {46E6D6E9-7A30-4058-9661-DF70CC07E821}
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A} = {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "picotls", "picotls\picotls.vcxproj", "{46E6D6E9-7A30-4058-9661-DF70CC07E821}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testopenssl", "testopenssl\testopenssl.vcxproj", "{8750EE3B-9440-48BF-8D83-7274E94B06A7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440} = {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821} = {46E6D6E9-7A30-4058-9661-DF70CC07E821}
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A} = {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "microecc", "microecc\microecc.vcxproj", "{3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cifra", "cifra\cifra.vcxproj", "{5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Debug|x64.ActiveCfg = Debug|x64
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Debug|x64.Build.0 = Debug|x64
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Debug|x86.ActiveCfg = Debug|Win32
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Debug|x86.Build.0 = Debug|Win32
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x64.ActiveCfg = Release|x64
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x64.Build.0 = Release|x64
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x86.ActiveCfg = Release|Win32
+ {D0265367-FCCF-47A4-95FD-C33BECAB3486}.Release|x86.Build.0 = Release|Win32
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x64.ActiveCfg = Debug|x64
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x64.Build.0 = Debug|x64
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x86.ActiveCfg = Debug|Win32
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Debug|x86.Build.0 = Debug|Win32
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x64.ActiveCfg = Release|x64
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x64.Build.0 = Release|x64
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x86.ActiveCfg = Release|Win32
+ {46E6D6E9-7A30-4058-9661-DF70CC07E821}.Release|x86.Build.0 = Release|Win32
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x64.ActiveCfg = Debug|x64
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x64.Build.0 = Debug|x64
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x86.ActiveCfg = Debug|Win32
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Debug|x86.Build.0 = Debug|Win32
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x64.ActiveCfg = Release|x64
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x64.Build.0 = Release|x64
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x86.ActiveCfg = Release|Win32
+ {8750EE3B-9440-48BF-8D83-7274E94B06A7}.Release|x86.Build.0 = Release|Win32
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x64.ActiveCfg = Debug|x64
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x64.Build.0 = Debug|x64
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x86.ActiveCfg = Debug|Win32
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Debug|x86.Build.0 = Debug|Win32
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x64.ActiveCfg = Release|x64
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x64.Build.0 = Release|x64
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x86.ActiveCfg = Release|Win32
+ {3440FDEA-84D2-4424-BB19-B4B26A6ADC8A}.Release|x86.Build.0 = Release|Win32
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x64.ActiveCfg = Debug|x64
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x64.Build.0 = Debug|x64
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x86.ActiveCfg = Debug|Win32
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Debug|x86.Build.0 = Debug|Win32
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x64.ActiveCfg = Release|x64
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x64.Build.0 = Release|x64
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x86.ActiveCfg = Release|Win32
+ {5D4DA3A3-7851-4CAE-AE4F-C421A2C8C440}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ReadMe.txt b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ReadMe.txt
new file mode 100644
index 00000000..b12bf060
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ReadMe.txt
@@ -0,0 +1,40 @@
+========================================================================
+ CONSOLE APPLICATION : picotlsvs Project Overview
+========================================================================
+
+AppWizard has created this picotlsvs application for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your picotlsvs application.
+
+
+picotlsvs.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+picotlsvs.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+picotlsvs.cpp
+ This is the main application source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named picotlsvs.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/cert.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/cert.pem
new file mode 100644
index 00000000..a7fbf0a0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/cert.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhgCCQDKfyE0Al0a3TANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJV
+UzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4GA1UE
+CgwHRXhhbXBsZTESMBAGA1UEAwwJTG9jYWxIb3N0MB4XDTE3MDYyNjA0NDUzMloX
+DTE4MDYyNjA0NDUzMlowWjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0
+b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB0V4YW1wbGUxEjAQBgNVBAMM
+CUxvY2FsSG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALk0szcy
+JGaCu3N1l3e4oippgWn8COAckw1DDUvp9ml8bZnaZ841nbCA38O6Blnu1gxgS/F8
+FSIu29z4bJPQgStYOTxbxGym/jHMzbS9xzI5Byv3+G7tu/1QEoHcm9DyzSiIvWqM
+ytkloPdEgl+qUinWjvWGht9QzPSk6vNSM1Vqd2Gz7ZJIxNp6muzaSd5mQBSeO1AO
+uIhyIhIWMPpeR3BrtI2PCj5svrQ5OVlyKc6yoXYKDUFxIEKhOwjCU027ACdJRDcD
+WW+GzqR4EamWztQ016YcrlAa0PpAewDa1FQoXWy6Gl+6YF8GIhn+ZHsJN0RgdqKE
+u1bkhL7iUl4vnjcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAEZjmYK+qoXImkUw3
+mangy2sUt9UHLQENGBhLbaMny8RRxcKedpf8COwsP56ONyZazzzyUgjlphQhunEe
+HsNQWD7s04cC3wuNWXvnFW/MsABjnzrGk1m6VDc5uxqBSrFFP1UtqwMleDIlgzVw
+H2mx4R1IyhGW+BYkDBwWpHmMFR9fXjdkVSzb5THwhhq7y2xJhrkKhj/iCTGlIMke
+d207w3vqw1X6dep1CMYj/B+ar/3l5AJSr+K1jsqVIzHugGuRMtV5DsKtS/DNqXG5
+sP+2YA/ohrXv/MCzHzVZ77lCetj7jHl2muX3rLF4IVTKWMrpi18ZwobB3JieFy1h
+WZydqg==
+-----END CERTIFICATE-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_cert.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_cert.pem
new file mode 100644
index 00000000..51bf0443
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_cert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICITCCAcigAwIBAgIJAJpmLpw+2sHYMAkGByqGSM49BAEwQzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMRUwEwYDVQQKEwxQaWNv
+VExTIFRlc3QwHhcNMTcwNzI1MDQyOTAyWhcNMTgwNzI1MDQyOTAyWjBDMQswCQYD
+VQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxFTATBgNVBAoT
+DFBpY29UTFMgVGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABK3/SPaRAh80
+1BERnxzh1Fi1FZtYGPmbMPoQNpkPchxwSsJBcm+IwOh0xtK/a+xKqOFjpVo8i7SW
+ARulK3XErOmjgaUwgaIwHQYDVR0OBBYEFA3LAgzzAyPVpIG0jsz1QSYQrMUgMHMG
+A1UdIwRsMGqAFA3LAgzzAyPVpIG0jsz1QSYQrMUgoUekRTBDMQswCQYDVQQGEwJV
+UzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxFTATBgNVBAoTDFBpY29U
+TFMgVGVzdIIJAJpmLpw+2sHYMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNIADBF
+AiAKr/C59Tfk+edPt6LBvNErf1x8HyD5mSmidjmMTznvQQIhALxOamTazSM0U0iL
+4IUfSjOChw4W1DWIRPDjZm97HEpY
+-----END CERTIFICATE-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_key.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_key.pem
new file mode 100644
index 00000000..29932c1c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/ec_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8rWCKftLG3r00UO8
+BKfR3+4jyiyyo9mz3UIDA+iATXyhRANCAASt/0j2kQIfNNQREZ8c4dRYtRWbWBj5
+mzD6EDaZD3IccErCQXJviMDodMbSv2vsSqjhY6VaPIu0lgEbpSt1xKzp
+-----END PRIVATE KEY-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-1.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-1.pem
new file mode 100644
index 00000000..1fb5f17b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-1.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgVcB/UNPxalR9zDYAjQIf
+jojUDiQuGnSJrFEEzZPT/92hRANCAASc7UJtgnF/abqWM60T3XNJEzBv5ez9TdwK
+H0M6xpM2q+53wmsN/eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ
+-----END PRIVATE KEY-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-2.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-2.pem
new file mode 100644
index 00000000..f4aeb5ef
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-2.pem
@@ -0,0 +1,9 @@
+-----BEGIN PRIVATE KEY-----
+MIIBMAIBADCB0wYHKoZIzj0CATCBxwIBATAkBgcqhkjOPQEBAhkA////////////
+/////////v//////////MEsEGP////////////////////7//////////AQYIhI9
+wjlaBcqnQj2uzMlHYKfUYiVr1WkWAxUAxGloRDXes3jEtlypWR4qV2MFmi4EMQR9
+KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rKdkipQ7AC
+GQD///////////////96YtAxyD9ClPZA7BMCAQEEVTBTAgEBBBiKtwssqrxHY/gu
+KDD4QgmyLDKaqBv2wEWhNAMyAAT5j6o+ojeB6jaFAfx4rtGf5hYbT1N6NnlAWiP1
++bEWtTJiEVqnpeZN0m0SLybIGZY=
+-----END PRIVATE KEY----- \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-3.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-3.pem
new file mode 100644
index 00000000..08c9496a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-3.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHQCAQEEILNvumjK/H0ioec3gNnn07vM/yDUfwAlInWQYtTY+NpsoAcGBSuBBAAK
+oUQDQgAEVw4JNyAuRNukW7+FFRLZW2Y8dNTAZ3SJp5AB+P+becKkbwtLLlO+PENe
+7ZC02lGb4Sak2Wc2jBdsheCzfJOloQ==
+-----END EC PRIVATE KEY-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-4.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-4.pem
new file mode 100644
index 00000000..4018db1c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key-test-4.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgocwnJPlQe7sRiRc0obuy
+ddukwdOK73PgNnqZUIFm64WhRANCAAQ1FDasoi8+SmGUBtKW5brq9+gCiE/Ymz53
+BPUYN8AeHABM64AqWwX0oFCM027E4qRjGGjd7O+T+M/tXTJJR5p4
+-----END PRIVATE KEY-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key.pem
new file mode 100644
index 00000000..8f86e717
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5NLM3MiRmgrtz
+dZd3uKIqaYFp/AjgHJMNQw1L6fZpfG2Z2mfONZ2wgN/DugZZ7tYMYEvxfBUiLtvc
++GyT0IErWDk8W8Rspv4xzM20vccyOQcr9/hu7bv9UBKB3JvQ8s0oiL1qjMrZJaD3
+RIJfqlIp1o71hobfUMz0pOrzUjNVandhs+2SSMTaeprs2kneZkAUnjtQDriIciIS
+FjD6Xkdwa7SNjwo+bL60OTlZcinOsqF2Cg1BcSBCoTsIwlNNuwAnSUQ3A1lvhs6k
+eBGpls7UNNemHK5QGtD6QHsA2tRUKF1suhpfumBfBiIZ/mR7CTdEYHaihLtW5IS+
+4lJeL543AgMBAAECggEARINOWPjfplxuY8P4iH1w4CevjDmEPwPTEnDfllmyoks5
+cFTvWcVT1FuYa5uBhftoi6OD9I1mdALJqvDrmbLkVdiJM97uxxLvrhSJdHdQHTAj
+iwxshvzDMm5QqmGl8qIfawNKrwPudm4JIe/iGumzA28v63wcoLgPWeE4WVLrUoky
+WUc4eOhdqgB1I1Ma/pOZGIMMF8kdmvqau7XSrc7u51wAQgf8Y+MF6E2WWwKLfd75
+oWlmyJtzY0zVQ+brHmRPMiwvWwtoahLS1rVvkLf62bWlUcVT4IEDNhd0Igftee7n
+0G+GEpaVjL+FGdnzJ9EVsTH7CQ7fPS0E1fvm0BK7IQKBgQDvId7NHGUgkw2Ekdu0
+CXrSo52ZEDEFt0yyv1RYCWk+IWF3IOj2QIGQ5cR9fQPI0sKXU4poMgIbEv2NRnVY
+JIQ11Z8tXQe9+Hk56MvhjQhni6WwmuoNTw6yGlWFMWZgkKauSNaQW0v+CdCDlG2o
+I1Iuv4nT1sq9orT2uxQVr6PNqwKBgQDGRQ2p+9CQyFqjg8A39niLrqAH4nd4O5/H
+Mc5orbLNAxEWH09MFZPl11+WTksVlhPcrvKczYUcQsVAW1MIB46VtRjyJ8wC+RE+
++ayLR26PpPgUgfuz/dPytDdi2e3Y5vtZ6ZDwVfwBEUfYoC9TcunJWaIXIJpvyUJp
+3sxJJF8tpQKBgQDUUiFtwnFz271b4NnO37/i+Iz8k2jDZ329E65CwJBmLuNID7to
+sduYmLm+pdpPW/qUvAMfAo/mFBV2c4HK8hlFZ1f+wiQWo2CXb0BfEobM0SwbQ2De
+0jv9HO6j5Tm+MZEdG+UOpVEyzOoLeiVm7X2RrlUk9whqGeZNT8vEeX+aIwKBgQCc
+ueckME7cs9OaH8JpOmZtnBsaQHVJ0G/ryL4t1uhY0IzIHPXU4dWoQMhpivglVx3a
+O1zCgF8xSMKdrdMDrN2UD7RpbvYAf5uXWUuASXXnDHOh2mH6FLJezwBdHoG6DFQx
+7cRJht6OhXdykKT4ZQTSygysFXSe2sup3plDVAH8lQKBgECy9w2481N3RoET7Z0x
+1RHQSLNduFBOekdBMmJzbQJm1r5G+j9iUrwESboi5ZwodpMT3DS+rXye6GmJhOKi
+e+M3uATC+lsHnU3AInf/t3N8NvYS9AOIkWV/p/+IjzMPTyEJH2nUBUZA8f32bcnL
+3qG4F2xvUiz0/vVrbQyJm/LQ
+-----END PRIVATE KEY-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/myec1.pem b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/myec1.pem
new file mode 100644
index 00000000..8a19bb09
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/myec1.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHQCAQEEIKHMJyT5UHu7EYkXNKG7snXbpMHTiu9z4DZ6mVCBZuuFoAcGBSuBBAAK
+oUQDQgAENRQ2rKIvPkphlAbSluW66vfoAohP2Js+dwT1GDfAHhwATOuAKlsF9KBQ
+jNNuxOKkYxho3ezvk/jP7V0ySUeaeA==
+-----END EC PRIVATE KEY-----
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/openssl.cnf b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/openssl.cnf
new file mode 100644
index 00000000..c96e8432
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/openssl.cnf
@@ -0,0 +1,35 @@
+[ req ]
+default_bits = 1024
+default_keyfile= privkey.pem
+distinguished_name = req_distinguished_name
+
+
+[ req_distinguished_name ]
+countryName= US
+countryName_min= 2
+countryName_max = 2
+stateOrProvinceName= Washington
+localityName = Seattle
+organizationName = Example
+commonName = Localhost
+commonName_max = 64
+emailAddress = localhost@example.com
+emailAddress_max = 40
+
+
+[ alternate_names ]
+
+DNS.1 = example.com
+DNS.2 = www.example.com
+DNS.3 = mail.example.com
+DNS.4 = ftp.example.com
+
+# Add these if you need them. But usually you don't want them or
+# need them in production. You may need them for development.
+# DNS.5 = localhost
+# DNS.6 = localhost.localdomain
+# DNS.7 = 127.0.0.1
+
+# IPv6 localhost
+# DNS.8 = ::1
+
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.c b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.c
new file mode 100644
index 00000000..251b2909
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.c
@@ -0,0 +1,674 @@
+/* picotlsvs: test program for the TLS 1.3 library. */
+#include <stdio.h>
+#include <stdarg.h>
+#include <openssl/pem.h>
+#include "../picotls/wincompat.h"
+#include "../../include/picotls.h"
+#include "../../include/picotls/openssl.h"
+#include "../../include/picotls/minicrypto.h"
+#include "../../include/picotls/asn1.h"
+#include "../../include/picotls/pembase64.h"
+
+void log_printf(void * ctx, const char * format, ...)
+{
+ va_list argptr;
+ va_start(argptr, format);
+ vfprintf(stderr, format, argptr);
+}
+
+ptls_minicrypto_log_ctx_t log_ctx = { NULL, log_printf };
+
+int ptls_export_secret(ptls_t *tls, void *output, size_t outlen, const char *label, ptls_iovec_t context_value, int is_early);
+
+/*
+ * Testing the Base64 and ASN1 verifiers.
+ * Start by loading the private key object, then do a mini fuzz test.
+ * The goal is to verify that the decoding returns something correct,
+ * even in presence of errors.
+ */
+
+size_t ptls_minicrypto_asn1_decode_private_key(
+ ptls_asn1_pkcs8_private_key_t * pkey,
+ int * decode_error, ptls_minicrypto_log_ctx_t * log_ctx);
+
+int openPemTest(char const * filename)
+{
+ ptls_iovec_t buf = { 0 };
+ size_t count = 1;
+ size_t fuzz_index = 0;
+ uint8_t original_byte = 0;
+ uint8_t fuzz_byte = 0xAA;
+ size_t byte_index = 0;
+ int decode_error;
+
+ int ret = ptls_load_pem_objects(filename, "PRIVATE KEY", &buf, 1, &count);
+
+
+ if (ret == 0)
+ {
+ for (fuzz_index = 0; ret == 0 && fuzz_index < buf.len; fuzz_index++)
+ {
+ ptls_asn1_pkcs8_private_key_t pkey = { {0} };
+ original_byte = buf.base[fuzz_index];
+ decode_error = 0;
+ buf.base[fuzz_index] ^= fuzz_byte;
+
+ pkey.vec.base = buf.base;
+ pkey.vec.len = buf.len;
+
+ byte_index = ptls_minicrypto_asn1_decode_private_key(
+ &pkey, &decode_error, NULL);
+
+ if (decode_error != 0)
+ {
+ if (decode_error == 1)
+ {
+ ret = -1;
+ }
+ }
+
+ buf.base[fuzz_index] = original_byte;
+ }
+ }
+
+ if (buf.base != NULL)
+ {
+ free(buf.base);
+ }
+
+ return ret;
+}
+
+/*
+ * Using the open ssl library to load the test certificate
+ */
+
+X509* openPemFile(char* filename)
+{
+
+ X509* cert = X509_new();
+ BIO* bio_cert = BIO_new_file(filename, "rb");
+ PEM_read_bio_X509(bio_cert, &cert, NULL, NULL);
+ return cert;
+}
+
+int get_certificates(char * pem_fname, ptls_iovec_t ** list, int * nb_certs)
+{
+ int ret = 0;
+ size_t count = 0;
+ X509 *cert;
+ static ptls_iovec_t certs[16];
+
+ *nb_certs = 0;
+ *list = NULL;
+
+ cert = openPemFile(pem_fname);
+
+ if (cert == NULL)
+ {
+ fprintf(stderr, "Could not read cert in %s\n", pem_fname);
+ ret = -1;
+ }
+ else
+ {
+ ptls_iovec_t *dst = certs + count++;
+ dst->len = i2d_X509(cert, &dst->base);
+ }
+
+ *nb_certs = (int) count;
+ *list = certs;
+
+ return ret;
+}
+
+void SetSignCertificate(char * keypem, ptls_context_t * ctx)
+{
+ static ptls_openssl_sign_certificate_t signer;
+
+ EVP_PKEY *pkey = EVP_PKEY_new();
+ BIO* bio_key = BIO_new_file(keypem, "rb");
+ PEM_read_bio_PrivateKey(bio_key, &pkey, NULL, NULL);
+ ptls_openssl_init_sign_certificate(&signer, pkey);
+ EVP_PKEY_free(pkey);
+ ctx->sign_certificate = &signer.super;
+}
+
+int handshake_init(ptls_t * tls, ptls_buffer_t * sendbuf, ptls_handshake_properties_t * ph_prop)
+{
+ size_t inlen = 0, roff = 0;
+
+ ptls_buffer_init(sendbuf, "", 0);
+ int ret = ptls_handshake(tls, sendbuf, NULL, NULL, ph_prop);
+
+ return ret;
+}
+
+
+int handshake_progress(ptls_t * tls, ptls_buffer_t * sendbuf, ptls_buffer_t * recvbuf, ptls_handshake_properties_t * ph_prop)
+{
+ size_t inlen = 0, roff = 0;
+ int ret = 0;
+
+ ptls_buffer_init(sendbuf, "", 0);
+
+ /* Provide the data */
+ while (roff < recvbuf->off && (ret == 0 || ret == PTLS_ERROR_IN_PROGRESS))
+ {
+ inlen = recvbuf->off - roff;
+ ret = ptls_handshake(tls, sendbuf, recvbuf->base + roff, &inlen, ph_prop);
+ roff += inlen;
+ }
+
+ if (roff < recvbuf->off)
+ {
+ // Could not consume all the data. This is bad.
+ fprintf(stderr, "Could only process %d bytes out of %d\n", (int) roff, (int) recvbuf->off);
+ }
+ ptls_buffer_dispose(recvbuf);
+
+ return ret;
+}
+
+/*
+ Verify the secret extraction functionality
+ at the end of the handshake.
+ */
+
+int extract_1rtt_secret(
+ ptls_t *tls, const char *label,
+ ptls_cipher_suite_t ** cipher,
+ uint8_t * secret, size_t secret_max)
+{
+ int ret = 0;
+ *cipher = ptls_get_cipher(tls);
+
+ if (*cipher == NULL)
+ {
+ ret = -1;
+ }
+ else if ((*cipher)->hash->digest_size > secret_max)
+ {
+ ret = -1;
+ }
+ else
+ {
+ ret = ptls_export_secret(tls, secret, (*cipher)->hash->digest_size,
+ label, ptls_iovec_init(NULL, 0), 1);
+ }
+
+ return 0;
+}
+
+int verify_1rtt_secret_extraction(ptls_t *tls_client, ptls_t *tls_server)
+{
+ int ret = 0;
+ ptls_cipher_suite_t * cipher_client;
+ ptls_cipher_suite_t * cipher_server;
+ uint8_t secret_client[64];
+ uint8_t secret_server[64];
+ char const * label = "This is just a test";
+
+ ret = extract_1rtt_secret(tls_client, label, &cipher_client,
+ secret_client, sizeof(secret_client));
+
+ if (ret != 0)
+ {
+ fprintf(stderr, "Cannot extract client 1RTT secret, ret=%d\n", ret);
+ }
+ else
+ {
+ ret = extract_1rtt_secret(tls_server, label, &cipher_server,
+ secret_server, sizeof(secret_server));
+ if (ret != 0)
+ {
+ fprintf(stderr, "Cannot extract client 1RTT secret, ret=%d\n", ret);
+ }
+ }
+
+ if (ret == 0)
+ {
+ if (strcmp(cipher_client->aead->name, cipher_server->aead->name) != 0)
+ {
+ fprintf(stderr, "AEAD differ, client:%s, server:%s\n",
+ cipher_client->aead->name, cipher_server->aead->name);
+ ret = -1;
+ }
+ else if (cipher_client->hash->digest_size != cipher_server->hash->digest_size)
+ {
+ fprintf(stderr, "Key length differ, client:%d, server:%d\n",
+ (int) cipher_client->hash->digest_size, (int) cipher_server->hash->digest_size);
+ ret = -1;
+ }
+ else if (memcmp(secret_client, secret_server, cipher_client->hash->digest_size) != 0)
+ {
+ fprintf(stderr, "Key of client and server differ!\n");
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+int openssl_init_test_client(ptls_context_t *ctx_client)
+{
+ int ret = 0;
+ static ptls_openssl_verify_certificate_t verifier;
+
+ /* Initialize the client context */
+ memset(ctx_client, 0, sizeof(ptls_context_t));
+ ctx_client->random_bytes = ptls_openssl_random_bytes;
+ ctx_client->get_time = &ptls_get_time;
+ ctx_client->key_exchanges = ptls_openssl_key_exchanges;
+ ctx_client->cipher_suites = ptls_openssl_cipher_suites;
+ ptls_openssl_init_verify_certificate(&verifier, NULL);
+ ctx_client->verify_certificate = &verifier.super;
+
+ return ret;
+}
+
+int openssl_init_test_server(ptls_context_t *ctx_server, char * key_file, char * cert_file)
+{
+ int ret = 0;
+ /* Initialize the server context */
+ memset(ctx_server, 0, sizeof(ptls_context_t));
+ ctx_server->random_bytes = ptls_openssl_random_bytes;
+ ctx_server->get_time = &ptls_get_time;
+ ctx_server->key_exchanges = ptls_openssl_key_exchanges;
+ ctx_server->cipher_suites = ptls_openssl_cipher_suites;
+
+ ret = ptls_load_certificates(ctx_server, cert_file);
+ if (ret != 0)
+ {
+ fprintf(stderr, "Could not read the server certificates\n");
+ }
+ else
+ {
+ SetSignCertificate(key_file, ctx_server);
+ }
+
+ return ret;
+}
+
+int minicrypto_init_test_client(ptls_context_t *ctx_client)
+{
+ int ret = 0;
+ // static ptls_openssl_verify_certificate_t verifier;
+
+ /* Initialize the client context */
+ memset(ctx_client, 0, sizeof(ptls_context_t));
+ ctx_client->random_bytes = ptls_minicrypto_random_bytes;
+ ctx_client->get_time = &ptls_get_time;
+ ctx_client->key_exchanges = ptls_minicrypto_key_exchanges;
+ ctx_client->cipher_suites = ptls_minicrypto_cipher_suites;
+ // ptls_openssl_init_verify_certificate(&verifier, NULL);
+ ctx_client->verify_certificate = NULL; // &verifier.super;
+
+ return ret;
+}
+
+int minicrypto_init_test_server(ptls_context_t *ctx_server, char * key_file, char * cert_file)
+{
+ int ret = 0;
+
+ /* Initialize the server context */
+ memset(ctx_server, 0, sizeof(ptls_context_t));
+ ctx_server->random_bytes = ptls_minicrypto_random_bytes;
+ ctx_server->get_time = &ptls_get_time;
+ ctx_server->key_exchanges = ptls_minicrypto_key_exchanges;
+ ctx_server->cipher_suites = ptls_minicrypto_cipher_suites;
+
+ ret = ptls_load_certificates(ctx_server, cert_file);
+
+ if (ret != 0)
+ {
+ fprintf(stderr, "Could not read the server certificates\n");
+ }
+ else
+ {
+ ret = ptls_minicrypto_load_private_key(ctx_server, key_file);
+ }
+
+ return ret;
+}
+
+#define PICOTLS_VS_TEST_EXTENSION 1234
+static uint8_t testExtensionClient[] = { 1, 2, 3 };
+static uint8_t testExtensionServer[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+char const test_sni[] = "picotls.example.com";
+char const test_alpn[] = "picotls";
+static const ptls_iovec_t proposed_alpn[] = {
+ { (uint8_t *) "grease", 6},
+ { (uint8_t *)test_alpn, sizeof(test_alpn) -1 }
+};
+
+
+struct st_picotls_vs_test_context_t
+{
+ int client_mode;
+ size_t received_extension_length;
+ uint8_t received_extension[16];
+ ptls_raw_extension_t ext[2];
+
+ ptls_handshake_properties_t handshake_properties;
+
+};
+
+int collect_test_extension(ptls_t *tls, struct st_ptls_handshake_properties_t *properties, uint16_t type)
+{
+ return type == PICOTLS_VS_TEST_EXTENSION;
+}
+
+void set_test_extensions(ptls_raw_extension_t ext[2], uint8_t * data, size_t len)
+{
+ ext[0].type = PICOTLS_VS_TEST_EXTENSION;
+ ext[0].data.base = data;
+ ext[0].data.len = len;
+ ext[1].type = 0xFFFF;
+ ext[1].data.base = NULL;
+ ext[1].data.len = 0;
+}
+
+int collected_test_extensions(ptls_t *tls, ptls_handshake_properties_t *properties,
+ ptls_raw_extension_t *slots)
+{
+ struct st_picotls_vs_test_context_t * ctx = (struct st_picotls_vs_test_context_t *)
+ ((char *)properties - offsetof(struct st_picotls_vs_test_context_t, handshake_properties));
+
+ if (slots[0].type == PICOTLS_VS_TEST_EXTENSION && slots[1].type == 0xFFFF)
+ {
+ ctx->received_extension_length = slots[0].data.len;
+ memcpy(ctx->received_extension, slots[0].data.base,
+ (slots[0].data.len < sizeof(ctx->received_extension)) ?
+ slots[0].data.len : sizeof(ctx->received_extension));
+
+ if (ctx->client_mode == 0)
+ {
+ properties->additional_extensions = ctx->ext;
+ set_test_extensions(ctx->ext, testExtensionServer, sizeof(testExtensionServer));
+ }
+ }
+
+ return 0;
+}
+
+int client_hello_call_back(ptls_on_client_hello_t * on_hello_cb_ctx,
+ ptls_t *tls, ptls_iovec_t server_name, const ptls_iovec_t *negotiated_protocols,
+ size_t num_negotiated_protocols, const uint16_t *signature_algorithms, size_t num_signature_algorithms)
+{
+ for (size_t i = 0; i < num_negotiated_protocols; i++)
+ {
+ if (negotiated_protocols[i].len == sizeof(test_alpn) - 1 &&
+ memcmp(negotiated_protocols[i].base, test_alpn, sizeof(test_alpn) - 1) == 0)
+ {
+ ptls_set_negotiated_protocol(tls, test_alpn, sizeof(test_alpn) - 1);
+ break;
+ }
+ }
+ return 0;
+}
+
+void set_handshake_context(struct st_picotls_vs_test_context_t * ctx, int client_mode)
+{
+ memset(ctx, 0, sizeof(struct st_picotls_vs_test_context_t));
+
+ if ((ctx->client_mode = client_mode) != 0)
+ {
+ ctx->handshake_properties.client.negotiated_protocols.list = proposed_alpn;
+ ctx->handshake_properties.client.negotiated_protocols.count =
+ sizeof(proposed_alpn) / sizeof(ptls_iovec_t);
+
+ ctx->handshake_properties.additional_extensions = ctx->ext;
+ set_test_extensions(ctx->ext, testExtensionClient, sizeof(testExtensionClient));
+ }
+
+ ctx->handshake_properties.collect_extension = collect_test_extension;
+ ctx->handshake_properties.collected_extensions = collected_test_extensions;
+}
+
+int verify_handshake_extension(struct st_picotls_vs_test_context_t * app_ctx_client,
+ struct st_picotls_vs_test_context_t *app_ctx_server)
+{
+ int ret = 0;
+
+ if (app_ctx_server->received_extension_length == 0)
+ {
+ fprintf(stderr, "Server did not receive the client extension.\n");
+ ret = -1;
+ }
+ else if (app_ctx_server->received_extension_length != sizeof(testExtensionClient) ||
+ memcmp(app_ctx_server->received_extension, testExtensionClient, sizeof(testExtensionClient)))
+ {
+ fprintf(stderr, "Server did not correctly receive the client extension.\n");
+ ret = -1;
+ }
+ else if (app_ctx_client->received_extension_length == 0)
+ {
+ fprintf(stderr, "Client did not receive the server extension.\n");
+ ret = -1;
+ }
+ else if (app_ctx_client->received_extension_length != sizeof(testExtensionServer) ||
+ memcmp(app_ctx_client->received_extension, testExtensionServer, sizeof(testExtensionServer)))
+ {
+ fprintf(stderr, "Client did not correctly receive the server extension.\n");
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int ptls_memory_loopback_test(int openssl_client, int openssl_server, char * key_file, char * cert_file)
+{
+ ptls_context_t ctx_client, ctx_server;
+ ptls_t *tls_client = NULL, *tls_server = NULL;
+ int ret = 0;
+ ptls_buffer_t client_buf, server_buf;
+ struct st_picotls_vs_test_context_t app_ctx_client, app_ctx_server;
+ ptls_on_client_hello_t client_hello_cb;
+
+
+ /* init the contexts */
+ if (ret == 0 && openssl_client)
+ {
+ ret = openssl_init_test_client(&ctx_client);
+ }
+ else
+ {
+ ret = minicrypto_init_test_client(&ctx_client);
+ }
+
+ if (ret == 0 && openssl_server)
+ {
+ ret = openssl_init_test_server(&ctx_server, key_file, cert_file);
+ }
+ else
+ {
+ ret = minicrypto_init_test_server(&ctx_server, key_file, cert_file);
+ }
+
+ /* Create the connections */
+ if (ret == 0)
+ {
+ tls_client = ptls_new(&ctx_client, 0);
+ tls_server = ptls_new(&ctx_server, 1);
+
+ if (tls_server == NULL || tls_client == NULL)
+ {
+ fprintf(stderr, "Could not create the TLS connection objects\n");
+ ret = -1;
+ }
+ }
+
+ /* Perform the handshake */
+ if (ret == 0)
+ {
+ int nb_rounds = 0;
+
+ set_handshake_context(&app_ctx_client, 1);
+ set_handshake_context(&app_ctx_server, 0);
+
+ client_hello_cb.cb = client_hello_call_back;
+ ctx_server.on_client_hello = &client_hello_cb;
+
+ ptls_set_server_name(tls_client, test_sni, sizeof(test_sni) - 1);
+
+ ret = handshake_init(tls_client, &client_buf,
+ &app_ctx_client.handshake_properties);
+ printf("First message from client, ret = %d, %d bytes.\n", ret, (int) client_buf.off);
+
+ while ((ret == 0 || ret == PTLS_ERROR_IN_PROGRESS) && client_buf.off > 0 && nb_rounds < 12)
+ {
+ nb_rounds++;
+
+ ret = handshake_progress(tls_server, &server_buf, &client_buf,
+ &app_ctx_server.handshake_properties);
+ app_ctx_server.handshake_properties.additional_extensions = NULL;
+
+ printf("Message from server, ret = %d, %d bytes.\n", ret, (int) server_buf.off);
+
+ if ((ret == 0 || ret == PTLS_ERROR_IN_PROGRESS) && server_buf.off > 0)
+ {
+ app_ctx_client.handshake_properties.additional_extensions = NULL;
+
+ ret = handshake_progress(tls_client, &client_buf, &server_buf,
+ &app_ctx_client.handshake_properties);
+
+ printf("Message from client, ret = %d, %d bytes.\n", ret, (int) client_buf.off);
+ }
+ }
+
+ printf("Exit handshake after %d rounds, ret = %d.\n", nb_rounds, ret);
+
+ if (ret == 0)
+ {
+ ret = verify_1rtt_secret_extraction(tls_client, tls_server);
+
+ if (ret == 0)
+ {
+ printf("Key extracted and matches!\n");
+ }
+ }
+
+ if (ret == 0)
+ {
+ ret = verify_handshake_extension(&app_ctx_client, &app_ctx_server);
+
+ if (ret == 0)
+ {
+ printf("Extensions received and match!\n");
+ }
+ }
+
+ if (ret == 0)
+ {
+ const char * sni_received = ptls_get_server_name(tls_server);
+
+ if (sni_received == NULL)
+ {
+ fprintf(stderr, "Server did not receive the SNI set by the client\n");
+ ret = -1;
+ }
+ else if (strcmp(sni_received, test_sni) != 0)
+ {
+ fprintf(stderr, "Server receives SNI: <%s>, does not match <%s>\n",
+ sni_received, test_sni);
+ ret = -1;
+ }
+ }
+
+ if (ret == 0)
+ {
+ const char * alpn_received = ptls_get_negotiated_protocol(tls_server);
+
+ if (alpn_received == NULL)
+ {
+ fprintf(stderr, "Server did not negotiate ALPN\n");
+ ret = -1;
+ }
+ else if (strcmp(alpn_received, test_alpn) != 0)
+ {
+ fprintf(stderr, "Server receives ALPN: <%s>, does not match <%s>\n",
+ alpn_received, test_alpn);
+ ret = -1;
+ }
+ }
+
+ if (ret == 0)
+ {
+ printf("SNI and ALPN match.\n");
+ }
+ }
+
+ if (tls_client != NULL)
+ {
+ ptls_free(tls_client);
+ }
+
+ if (tls_server != NULL)
+ {
+ ptls_free(tls_server);
+ }
+
+ if (openssl_server == 0 && ctx_server.sign_certificate != NULL)
+ {
+ free(ctx_server.sign_certificate);
+ }
+
+ return ret;
+}
+
+static char const * test_keys[] = {
+ "key.pem",
+ "ec_key.pem",
+ "key-test-1.pem",
+ "key-test-2.pem",
+ "key-test-4.pem"
+};
+
+static const size_t nb_test_keys = sizeof(test_keys) / sizeof(char const *);
+
+int main()
+{
+ int ret = 0;
+
+#if 1
+ /* TODO: move to ASN.1 unit test*/
+
+ for (size_t i = 0; ret == 0 && i < nb_test_keys; i++)
+ {
+ ret = openPemTest(test_keys[i]);
+ }
+#endif
+
+ if (ret == 0)
+ {
+ printf("\nStarting the RSA test with OpenSSL\n");
+ ret = ptls_memory_loopback_test(1, 1, "key.pem", "cert.pem");
+ }
+
+ if (ret == 0)
+ {
+ printf("\nStarting the P256R1 test with OpenSSL\n");
+ ret = ptls_memory_loopback_test(1, 1, "ec_key.pem", "ec_cert.pem");
+ }
+
+ if (ret == 0)
+ {
+ printf("\nStarting the P256R1 test with OpenSSL server and Minicrypto client\n");
+ ret = ptls_memory_loopback_test(0, 1, "ec_key.pem", "ec_cert.pem");
+ }
+
+ if (ret == 0)
+ {
+ printf("\nStarting the P256R1 test with Minicrypto\n");
+ ret = ptls_memory_loopback_test(0, 0, "ec_key.pem", "ec_cert.pem");
+ }
+
+ if (ret == 0)
+ {
+ printf("\nStarting the P256R1 test with Minicrypto server and OpenSSL client\n");
+ ret = ptls_memory_loopback_test(1, 0, "ec_key.pem", "ec_cert.pem");
+ }
+
+ return ret;
+}
+
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj
new file mode 100644
index 00000000..792cf302
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{D0265367-FCCF-47A4-95FD-C33BECAB3486}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>picotlsvs</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;libcrypto.lib;libssl.lib;microecc.lib;cifra.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(OPENSSLDIR)\include;$(ProjectDir)..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="picotlsvs.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.filters b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.filters
new file mode 100644
index 00000000..a52d6d47
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.filters
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="targetver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="picotlsvs.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.user b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.user
new file mode 100644
index 00000000..be250787
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/picotlsvs.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/targetver.h b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/targetver.h
new file mode 100644
index 00000000..87c0086d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/picotlsvs/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj b/web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj
new file mode 100644
index 00000000..f5bf9ba2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{8750EE3B-9440-48BF-8D83-7274E94B06A7}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>testopenssl</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSLDIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSLDIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(OPENSSLDIR);$(OutDir)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(ProjectDir)..\picotls;$(ProjectDir)..\..\include;$(ProjectDir)\..\..\deps\cifra\src;$(ProjectDir)\..\..\deps\cifra\src\ext;$(ProjectDir)\..\..\deps\micro-ecc;$(OPENSSL64DIR)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(OPENSSL64DIR);$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>picotls.lib;cifra.lib;microecc.lib;libcrypto.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\deps\picotest\picotest.c" />
+ <ClCompile Include="..\..\t\openssl.c" />
+ <ClCompile Include="..\..\t\picotls.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\deps\cifra\src\testnorx.katdata.inc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\deps\cifra\src\testsha.h" />
+ <ClInclude Include="..\..\deps\cifra\src\testutil.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj.filters b/web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj.filters
new file mode 100644
index 00000000..b6ccd2fb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/picotlsvs/testopenssl/testopenssl.vcxproj.filters
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\deps\picotest\picotest.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\t\picotls.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\t\openssl.c">
+ <Filter>Header Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\deps\cifra\src\testnorx.katdata.inc">
+ <Filter>Header Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\deps\cifra\src\testsha.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\deps\cifra\src\testutil.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/picotls/t/cli.c b/web/server/h2o/libh2o/deps/picotls/t/cli.c
new file mode 100644
index 00000000..fc734999
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/t/cli.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */
+#endif
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+#include "picotls.h"
+#include "picotls/openssl.h"
+#include "util.h"
+
+static void shift_buffer(ptls_buffer_t *buf, size_t delta)
+{
+ if (delta != 0) {
+ assert(delta <= buf->off);
+ if (delta != buf->off)
+ memmove(buf->base, buf->base + delta, buf->off - delta);
+ buf->off -= delta;
+ }
+}
+
+static int handle_connection(int sockfd, ptls_context_t *ctx, const char *server_name, const char *input_file,
+ ptls_handshake_properties_t *hsprop)
+{
+ ptls_t *tls = ptls_new(ctx, server_name == NULL);
+ ptls_buffer_t rbuf, encbuf, ptbuf;
+ char bytebuf[16384];
+ enum { IN_HANDSHAKE, IN_1RTT, IN_SHUTDOWN } state = IN_HANDSHAKE;
+ int inputfd = 0, ret = 0;
+ size_t early_bytes_sent = 0;
+ ssize_t ioret;
+
+ ptls_buffer_init(&rbuf, "", 0);
+ ptls_buffer_init(&encbuf, "", 0);
+ ptls_buffer_init(&ptbuf, "", 0);
+
+ fcntl(sockfd, F_SETFL, O_NONBLOCK);
+
+ if (input_file != NULL) {
+ if ((inputfd = open(input_file, O_RDONLY)) == -1) {
+ fprintf(stderr, "failed to open file:%s:%s\n", input_file, strerror(errno));
+ ret = 1;
+ goto Exit;
+ }
+ }
+ if (server_name != NULL) {
+ ptls_set_server_name(tls, server_name, 0);
+ if ((ret = ptls_handshake(tls, &encbuf, NULL, NULL, hsprop)) != PTLS_ERROR_IN_PROGRESS) {
+ fprintf(stderr, "ptls_handshake:%d\n", ret);
+ ret = 1;
+ goto Exit;
+ }
+ }
+
+ while (1) {
+ /* check if data is available */
+ fd_set readfds, writefds, exceptfds;
+ int maxfd = 0;
+ struct timeval timeout;
+ do {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ FD_SET(sockfd, &readfds);
+ if (encbuf.off != 0)
+ FD_SET(sockfd, &writefds);
+ FD_SET(sockfd, &exceptfds);
+ maxfd = sockfd + 1;
+ if (inputfd != -1) {
+ FD_SET(inputfd, &readfds);
+ FD_SET(inputfd, &exceptfds);
+ if (maxfd <= inputfd)
+ maxfd = inputfd + 1;
+ }
+ timeout.tv_sec = encbuf.off != 0 ? 0 : 3600;
+ timeout.tv_usec = 0;
+ } while (select(maxfd, &readfds, &writefds, &exceptfds, &timeout) == -1);
+
+ /* consume incoming messages */
+ if (FD_ISSET(sockfd, &readfds) || FD_ISSET(sockfd, &exceptfds)) {
+ size_t off = 0, leftlen;
+ while ((ioret = read(sockfd, bytebuf, sizeof(bytebuf))) == -1 && errno == EINTR)
+ ;
+ if (ioret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ /* no data */
+ ioret = 0;
+ } else if (ioret <= 0) {
+ goto Exit;
+ }
+ while ((leftlen = ioret - off) != 0) {
+ if (state == IN_HANDSHAKE) {
+ if ((ret = ptls_handshake(tls, &encbuf, bytebuf + off, &leftlen, hsprop)) == 0) {
+ state = IN_1RTT;
+ /* release data sent as early-data, if server accepted it */
+ if (hsprop->client.early_data_accepted_by_peer)
+ shift_buffer(&ptbuf, early_bytes_sent);
+ if (ptbuf.off != 0) {
+ if ((ret = ptls_send(tls, &encbuf, ptbuf.base, ptbuf.off)) != 0) {
+ fprintf(stderr, "ptls_send(1rtt):%d\n", ret);
+ goto Exit;
+ }
+ ptbuf.off = 0;
+ }
+ } else if (ret == PTLS_ERROR_IN_PROGRESS) {
+ /* ok */
+ } else {
+ fprintf(stderr, "ptls_handshake:%d\n", ret);
+ goto Exit;
+ }
+ } else {
+ if ((ret = ptls_receive(tls, &rbuf, bytebuf + off, &leftlen)) == 0) {
+ if (rbuf.off != 0) {
+ write(1, rbuf.base, rbuf.off);
+ rbuf.off = 0;
+ }
+ } else if (ret == PTLS_ERROR_IN_PROGRESS) {
+ /* ok */
+ } else {
+ fprintf(stderr, "ptls_receive:%d\n", ret);
+ goto Exit;
+ }
+ }
+ off += leftlen;
+ }
+ }
+
+ /* read input (and send if possible) */
+ if (inputfd != -1 && (FD_ISSET(inputfd, &readfds) || FD_ISSET(inputfd, &exceptfds))) {
+ while ((ioret = read(inputfd, bytebuf, sizeof(bytebuf))) == -1 && errno == EINTR)
+ ;
+ if (ioret > 0) {
+ ptls_buffer_pushv(&ptbuf, bytebuf, ioret);
+ if (state == IN_HANDSHAKE) {
+ size_t send_amount = 0;
+ if (hsprop->client.max_early_data_size != NULL) {
+ size_t max_can_be_sent = *hsprop->client.max_early_data_size;
+ if (max_can_be_sent > ptbuf.off)
+ max_can_be_sent = ptbuf.off;
+ send_amount = max_can_be_sent - early_bytes_sent;
+ }
+ if (send_amount != 0) {
+ if ((ret = ptls_send(tls, &encbuf, ptbuf.base, send_amount)) != 0) {
+ fprintf(stderr, "ptls_send(early_data):%d\n", ret);
+ goto Exit;
+ }
+ early_bytes_sent += send_amount;
+ }
+ } else {
+ if ((ret = ptls_send(tls, &encbuf, bytebuf, ioret)) != 0) {
+ fprintf(stderr, "ptls_send(1rtt):%d\n", ret);
+ goto Exit;
+ }
+ ptbuf.off = 0;
+ }
+ } else {
+ /* closed */
+ if (input_file != NULL)
+ close(inputfd);
+ inputfd = -1;
+ }
+ }
+
+ /* send any data */
+ if (encbuf.off != 0) {
+ while ((ioret = write(sockfd, encbuf.base, encbuf.off)) == -1 && errno == EINTR)
+ ;
+ if (ioret == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+ /* no data */
+ } else if (ioret <= 0) {
+ goto Exit;
+ } else {
+ shift_buffer(&encbuf, ioret);
+ }
+ }
+
+ /* close the sender side when necessary */
+ if (state == IN_1RTT && inputfd == -1) {
+ /* FIXME send close_alert */
+ shutdown(sockfd, SHUT_WR);
+ state = IN_SHUTDOWN;
+ }
+ }
+
+Exit:
+ if (sockfd != -1)
+ close(sockfd);
+ if (input_file != NULL && inputfd != -1)
+ close(inputfd);
+ ptls_buffer_dispose(&rbuf);
+ ptls_buffer_dispose(&encbuf);
+ ptls_buffer_dispose(&ptbuf);
+ ptls_free(tls);
+ return ret != 0;
+}
+
+static int run_server(struct sockaddr *sa, socklen_t salen, ptls_context_t *ctx, const char *input_file,
+ ptls_handshake_properties_t *hsprop)
+{
+ int listen_fd, conn_fd, on = 1;
+
+ if ((listen_fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) {
+ perror("socket(2) failed");
+ return 1;
+ }
+ if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
+ perror("setsockopt(SO_REUSEADDR) failed");
+ return 1;
+ }
+ if (bind(listen_fd, sa, salen) != 0) {
+ perror("bind(2) failed");
+ return 1;
+ }
+ if (listen(listen_fd, SOMAXCONN) != 0) {
+ perror("listen(2) failed");
+ return 1;
+ }
+
+ while (1) {
+ if ((conn_fd = accept(listen_fd, NULL, 0)) != -1)
+ handle_connection(conn_fd, ctx, NULL, input_file, hsprop);
+ }
+
+ return 0;
+}
+
+static int run_client(struct sockaddr *sa, socklen_t salen, ptls_context_t *ctx, const char *server_name, const char *input_file,
+ ptls_handshake_properties_t *hsprop)
+{
+ int fd;
+
+ if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == 1) {
+ perror("socket(2) failed");
+ return 1;
+ }
+ if (connect(fd, sa, salen) != 0) {
+ perror("connect(2) failed");
+ return 1;
+ }
+
+ return handle_connection(fd, ctx, server_name, input_file, hsprop);
+}
+
+static void usage(const char *cmd)
+{
+ printf("Usage: %s [options] host port\n"
+ "\n"
+ "Options:\n"
+ " -4 force IPv4\n"
+ " -6 force IPv6\n"
+ " -c certificate-file\n"
+ " -i file a file to read from and send to the peer (default: stdin)\n"
+ " -k key-file specifies the credentials to be used for running the\n"
+ " server. If omitted, the command runs as a client.\n"
+ " -l log-file file to log traffic secrets\n"
+ " -n negotiates the key exchange method (i.e. wait for HRR)\n"
+ " -s session-file file to read/write the session ticket\n"
+ " -S require public key exchange when resuming a session\n"
+ " -e when resuming a session, send first 8,192 bytes of input\n"
+ " as early data\n"
+ " -v verify peer using the default certificates\n"
+ " -h print this help\n"
+ "\n",
+ cmd);
+}
+
+int main(int argc, char **argv)
+{
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+#if !defined(OPENSSL_NO_ENGINE)
+ /* Load all compiled-in ENGINEs */
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_ciphers();
+ ENGINE_register_all_digests();
+#endif
+
+ ptls_context_t ctx = {ptls_openssl_random_bytes, &ptls_get_time, ptls_openssl_key_exchanges, ptls_openssl_cipher_suites};
+ ptls_handshake_properties_t hsprop = {{{{NULL}}}};
+ const char *host, *port, *file = NULL;
+ int use_early_data = 0, ch;
+ struct sockaddr_storage sa;
+ socklen_t salen;
+ int family = 0;
+
+ while ((ch = getopt(argc, argv, "46c:i:k:nes:Sl:vh")) != -1) {
+ switch (ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'c':
+ load_certificate_chain(&ctx, optarg);
+ break;
+ case 'i':
+ file = optarg;
+ break;
+ case 'k':
+ load_private_key(&ctx, optarg);
+ break;
+ case 'n':
+ hsprop.client.negotiate_before_key_exchange = 1;
+ break;
+ case 'e':
+ use_early_data = 1;
+ break;
+ case 's':
+ setup_session_file(&ctx, &hsprop, optarg);
+ break;
+ case 'S':
+ ctx.require_dhe_on_psk = 1;
+ break;
+ case 'l':
+ setup_log_secret(&ctx, optarg);
+ break;
+ case 'v':
+ setup_verify_certificate(&ctx);
+ break;
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (ctx.certificates.count != 0 || ctx.sign_certificate != NULL) {
+ /* server */
+ if (ctx.certificates.count == 0 || ctx.sign_certificate == NULL) {
+ fprintf(stderr, "-c and -k options must be used together\n");
+ return 1;
+ }
+ setup_session_cache(&ctx);
+ } else {
+ /* client */
+ if (use_early_data) {
+ static size_t max_early_data_size;
+ hsprop.client.max_early_data_size = &max_early_data_size;
+ }
+ }
+ if (argc != 2) {
+ fprintf(stderr, "missing host and port\n");
+ return 1;
+ }
+ host = (--argc, *argv++);
+ port = (--argc, *argv++);
+
+ if (resolve_address((struct sockaddr *)&sa, &salen, host, port, family, SOCK_STREAM, IPPROTO_TCP) != 0)
+ exit(1);
+
+ if (ctx.certificates.count != 0) {
+ return run_server((struct sockaddr *)&sa, salen, &ctx, file, &hsprop);
+ } else {
+ return run_client((struct sockaddr *)&sa, salen, &ctx, host, file, &hsprop);
+ }
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/t/minicrypto.c b/web/server/h2o/libh2o/deps/picotls/t/minicrypto.c
new file mode 100644
index 00000000..0c18a908
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/t/minicrypto.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "../deps/picotest/picotest.h"
+#include "../lib/cifra.c"
+#include "../lib/uecc.c"
+#include "test.h"
+
+static void test_secp256r1_key_exchange(void)
+{
+ test_key_exchange(&ptls_minicrypto_secp256r1);
+}
+
+static void test_x25519_key_exchange(void)
+{
+ test_key_exchange(&ptls_minicrypto_x25519);
+}
+
+static void test_secp256r1_sign(void)
+{
+ const char *msg = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef";
+ ptls_minicrypto_secp256r1sha256_sign_certificate_t signer = {{secp256r1sha256_sign}};
+ uint8_t pub[SECP256R1_PUBLIC_KEY_SIZE];
+ uint16_t selected;
+ ptls_buffer_t sigbuf;
+ uint32_t sigbuf_small[128];
+
+ uECC_make_key(pub, signer.key, uECC_secp256r1());
+ ptls_buffer_init(&sigbuf, sigbuf_small, sizeof(sigbuf_small));
+
+ ok(secp256r1sha256_sign(&signer.super, NULL, &selected, &sigbuf, ptls_iovec_init(msg, 32),
+ (uint16_t[]){PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256}, 1) == 0);
+ ok(selected == PTLS_SIGNATURE_ECDSA_SECP256R1_SHA256);
+
+ /* FIXME verify sign */
+
+ ptls_buffer_dispose(&sigbuf);
+}
+
+static void test_hrr(void)
+{
+ ptls_key_exchange_algorithm_t *client_keyex[] = {&ptls_minicrypto_x25519, &ptls_minicrypto_secp256r1, NULL};
+ ptls_context_t client_ctx = {ptls_minicrypto_random_bytes, &ptls_get_time, client_keyex, ptls_minicrypto_cipher_suites};
+ ptls_t *client, *server;
+ ptls_buffer_t cbuf, sbuf, decbuf;
+ uint8_t cbuf_small[16384], sbuf_small[16384], decbuf_small[16384];
+ size_t consumed;
+ int ret;
+
+ assert(ctx_peer->key_exchanges[0] != NULL && ctx_peer->key_exchanges[0]->id == PTLS_GROUP_SECP256R1);
+ assert(ctx_peer->key_exchanges[1] == NULL);
+
+ client = ptls_new(&client_ctx, 0);
+ server = ptls_new(ctx_peer, 1);
+ ptls_buffer_init(&cbuf, cbuf_small, sizeof(cbuf_small));
+ ptls_buffer_init(&sbuf, sbuf_small, sizeof(sbuf_small));
+ ptls_buffer_init(&decbuf, decbuf_small, sizeof(decbuf_small));
+
+ ret = ptls_handshake(client, &cbuf, NULL, NULL, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(consumed == cbuf.off);
+ cbuf.off = 0;
+
+ ok(sbuf.off > 5 + 4);
+ ok(sbuf.base[5] == 2 /* PTLS_HANDSHAKE_TYPE_SERVER_HELLO (RETRY_REQUEST) */);
+
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(consumed == sbuf.off);
+ sbuf.off = 0;
+
+ ok(cbuf.off >= 5 + 4);
+ ok(cbuf.base[5] == 1 /* PTLS_HANDSHAKE_TYPE_CLIENT_HELLO */);
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, NULL);
+ ok(ret == 0);
+ ok(consumed == cbuf.off);
+ cbuf.off = 0;
+
+ ok(sbuf.off >= 5 + 4);
+ ok(sbuf.base[5] == 2 /* PTLS_HANDSHAKE_TYPE_SERVER_HELLO */);
+
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, NULL);
+ ok(ret == 0);
+ ok(consumed == sbuf.off);
+ sbuf.off = 0;
+
+ ret = ptls_send(client, &cbuf, "hello world", 11);
+ ok(ret == 0);
+
+ consumed = cbuf.off;
+ ret = ptls_receive(server, &decbuf, cbuf.base, &consumed);
+ ok(ret == 0);
+ ok(consumed == cbuf.off);
+ cbuf.off = 0;
+
+ ok(decbuf.off == 11);
+ ok(memcmp(decbuf.base, "hello world", 11) == 0);
+
+ ptls_buffer_dispose(&decbuf);
+ ptls_buffer_dispose(&sbuf);
+ ptls_buffer_dispose(&cbuf);
+ ptls_free(client);
+ ptls_free(server);
+}
+
+int main(int argc, char **argv)
+{
+ subtest("secp256r1", test_secp256r1_key_exchange);
+ subtest("x25519", test_x25519_key_exchange);
+ subtest("secp256r1-sign", test_secp256r1_sign);
+
+ ptls_iovec_t cert = ptls_iovec_init(SECP256R1_CERTIFICATE, sizeof(SECP256R1_CERTIFICATE) - 1);
+
+ ptls_minicrypto_secp256r1sha256_sign_certificate_t sign_certificate;
+ ptls_minicrypto_init_secp256r1sha256_sign_certificate(&sign_certificate,
+ ptls_iovec_init(SECP256R1_PRIVATE_KEY, SECP256R1_PRIVATE_KEY_SIZE));
+
+ ptls_context_t ctxbuf = {ptls_minicrypto_random_bytes,
+ &ptls_get_time,
+ ptls_minicrypto_key_exchanges,
+ ptls_minicrypto_cipher_suites,
+ {&cert, 1},
+ NULL,
+ NULL,
+ &sign_certificate.super};
+ ctx = ctx_peer = &ctxbuf;
+
+ subtest("picotls", test_picotls);
+ subtest("hrr", test_hrr);
+
+ return done_testing();
+ return done_testing();
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/t/openssl.c b/web/server/h2o/libh2o/deps/picotls/t/openssl.c
new file mode 100644
index 00000000..9a7fc539
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/t/openssl.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifdef _WINDOWS
+#include "wincompat.h"
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/engine.h>
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+#include "../deps/picotest/picotest.h"
+#include "../lib/openssl.c"
+#include "test.h"
+
+#define RSA_PRIVATE_KEY \
+ "-----BEGIN RSA PRIVATE KEY-----\n" \
+ "MIIEowIBAAKCAQEA5soWzSG7iyawQlHM1yaX2dUAATUkhpbg2WPFOEem7E3zYzc6\n" \
+ "A/Z+bViFlfEgL37cbDUb4pnOAHrrsjGgkyBYh5i9iCTVfCk+H6SOHZJORO1Tq8X9\n" \
+ "C7WcNcshpSdm2Pa8hmv9hsHbLSeoPNeg8NkTPwMVaMZ2GpdmiyAmhzSZ2H9mzNI7\n" \
+ "ntPW/XCchVf+ax2yt9haZ+mQE2NPYwHDjqCtdGkP5ZXXnYhJSBzSEhxfGckIiKDy\n" \
+ "OxiNkLFLvUdT4ERSFBjauP2cSI0XoOUsiBxJNwHH310AU8jZbveSTcXGYgEuu2MI\n" \
+ "uDo7Vhkq5+TCqXsIFNbjy0taOoPRvUbPsbqFlQIDAQABAoIBAQCWcUv1wjR/2+Nw\n" \
+ "B+Swp267R9bt8pdxyK6f5yKrskGErremiFygMrFtVBQYjws9CsRjISehSkN4GqjE\n" \
+ "CweygJZVJeL++YvUmQnvFJSzgCjXU6GEStbOKD/A7T5sa0fmzMhOE907V+kpAT3x\n" \
+ "E1rNRaP/ImJ1X1GjuefVb0rOPiK/dehFQWfsUkOvh+J3PU76wcnexxzJgxhVxdfX\n" \
+ "qNa7UDsWzTImUjcHIfnhXc1K/oSKk6HjImQi/oE4lgoJUCEDaUbq0nXNrM0EmTTv\n" \
+ "OQ5TVP5Lds9p8UDEa55eZllGXam0zKjhDKtkQ/5UfnxsAv2adY5cuH+XN0ExfKD8\n" \
+ "wIZ5qINtAoGBAPRbQGZZkP/HOYA4YZ9HYAUQwFS9IZrQ8Y7C/UbL01Xli13nKalH\n" \
+ "xXdG6Zv6Yv0FCJKA3N945lEof9rwriwhuZbyrA1TcKok/s7HR8Bhcsm2DzRD5OiC\n" \
+ "3HK+Xy+6fBaMebffqBPp3Lfj/lSPNt0w/8DdrKBTw/cAy40g0n1zEu07AoGBAPHJ\n" \
+ "V4IfQBiblCqDh77FfQRUNR4hVbbl00Gviigiw563nk7sxdrOJ1edTyTOUBHtM3zg\n" \
+ "AT9sYz2CUXvsyEPqzMDANWMb9e2R//NcP6aM4k7WQRnwkZkp0WOIH95U2o1MHCYc\n" \
+ "5meAHVf2UMl+64xU2ZfY3rjMmPLjWMt0hKYsOmtvAoGAClIQVkJSLXtsok2/Ucrh\n" \
+ "81TRysJyOOe6TB1QNT1Gn8oiKMUqrUuqu27zTvM0WxtrUUTAD3A7yhG71LN1p8eE\n" \
+ "3ytAuQ9dItKNMI6aKTX0czCNU9fKQ0fDp9UCkDGALDOisHFx1+V4vQuUIl4qIw1+\n" \
+ "v9adA+iFzljqP/uy6DmEAyECgYAyWCgecf9YoFxzlbuYH2rukdIVmf9M/AHG9ZQg\n" \
+ "00xEKhuOd4KjErXiamDmWwcVFHzaDZJ08E6hqhbpZN42Nhe4Ms1q+5FzjCjtNVIT\n" \
+ "jdY5cCdSDWNjru9oeBmao7R2I1jhHrdi6awyeplLu1+0cp50HbYSaJeYS3pbssFE\n" \
+ "EIWBhQKBgG3xleD4Sg9rG2OWQz5IrvLFg/Hy7YWyushVez61kZeLDnt9iM2um76k\n" \
+ "/xFNIW0a+eL2VxRTCbXr9z86hjc/6CeSJHKYFQl4zsSAZkaIJ0+HbrhDNBAYh9b2\n" \
+ "mRdX+OMdZ7Z5J3Glt8ENFRqe8RlESMpAKxjR+dID0bjwAjVr2KCh\n" \
+ "-----END RSA PRIVATE KEY-----\n"
+
+#define RSA_CERTIFICATE \
+ "-----BEGIN CERTIFICATE-----\n" \
+ "MIICqDCCAZACCQDI5jeEvExN+TANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQDEwtl\n" \
+ "eGFtcGxlLmNvbTAeFw0xNjA5MzAwMzQ0NTFaFw0yNjA5MjgwMzQ0NTFaMBYxFDAS\n" \
+ "BgNVBAMTC2V4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\n" \
+ "AQEA5soWzSG7iyawQlHM1yaX2dUAATUkhpbg2WPFOEem7E3zYzc6A/Z+bViFlfEg\n" \
+ "L37cbDUb4pnOAHrrsjGgkyBYh5i9iCTVfCk+H6SOHZJORO1Tq8X9C7WcNcshpSdm\n" \
+ "2Pa8hmv9hsHbLSeoPNeg8NkTPwMVaMZ2GpdmiyAmhzSZ2H9mzNI7ntPW/XCchVf+\n" \
+ "ax2yt9haZ+mQE2NPYwHDjqCtdGkP5ZXXnYhJSBzSEhxfGckIiKDyOxiNkLFLvUdT\n" \
+ "4ERSFBjauP2cSI0XoOUsiBxJNwHH310AU8jZbveSTcXGYgEuu2MIuDo7Vhkq5+TC\n" \
+ "qXsIFNbjy0taOoPRvUbPsbqFlQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAwZQsG\n" \
+ "E/3DQFBOnmBITFsaIVJVXU0fbfIjy3p1r6O9z2zvrfB1i8AMxOORAVjE5wHstGnK\n" \
+ "3sLMjkMYXqu1XEfQbStQN+Bsi8m+nE/x9MmuLthpzJHXUmPYZ4TKs0KJmFPLTXYi\n" \
+ "j0OrP0a5BNcyGj/B4Z33aaU9N3z0TWBwx4OPjJoK3iInBx80sC1Ig2PE6mDBxLOg\n" \
+ "5Ohm/XU/43MrtH8SgYkxr3OyzXTm8J0RFMWhYlo1uqR+pWV3TgacixNnUq5w5h4m\n" \
+ "sqXcikh+j8ReNXsKnMOAfFo+HbRqyKWNE3DekCIiiQ5ds4A4SfT7pYyGAmBkAxht\n" \
+ "sS919x2o8l97kaYf\n" \
+ "-----END CERTIFICATE-----\n"
+
+static void test_ecdh_key_exchange(void)
+{
+ test_key_exchange(&ptls_openssl_secp256r1);
+}
+
+static void test_rsa_sign(void)
+{
+ ptls_openssl_sign_certificate_t *sc = (ptls_openssl_sign_certificate_t *)ctx->sign_certificate;
+
+ const void *message = "hello world";
+ ptls_buffer_t sigbuf;
+ uint8_t sigbuf_small[1024];
+
+ ptls_buffer_init(&sigbuf, sigbuf_small, sizeof(sigbuf_small));
+ ok(do_sign(sc->key, &sigbuf, ptls_iovec_init(message, strlen(message)), EVP_sha256()) == 0);
+ EVP_PKEY_up_ref(sc->key);
+ ok(verify_sign(sc->key, ptls_iovec_init(message, strlen(message)), ptls_iovec_init(sigbuf.base, sigbuf.off)) == 0);
+
+ ptls_buffer_dispose(&sigbuf);
+}
+
+static void test_ecdsa_sign(void)
+{
+ EVP_PKEY *pkey;
+
+ { /* create pkey */
+ EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ EC_KEY_generate_key(eckey);
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_EC_KEY(pkey, eckey);
+ EC_KEY_free(eckey);
+ }
+
+ const char *message = "hello world";
+ ptls_buffer_t sigbuf;
+ uint8_t sigbuf_small[1024];
+
+ ptls_buffer_init(&sigbuf, sigbuf_small, sizeof(sigbuf_small));
+ ok(do_sign(pkey, &sigbuf, ptls_iovec_init(message, strlen(message)), EVP_sha256()) == 0);
+ EVP_PKEY_up_ref(pkey);
+ ok(verify_sign(pkey, ptls_iovec_init(message, strlen(message)), ptls_iovec_init(sigbuf.base, sigbuf.off)) == 0);
+
+ ptls_buffer_dispose(&sigbuf);
+ EVP_PKEY_free(pkey);
+}
+
+static void setup_certificate(ptls_iovec_t *dst)
+{
+ BIO *bio = BIO_new_mem_buf(RSA_CERTIFICATE, strlen(RSA_CERTIFICATE));
+ X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+ assert(cert != NULL || !!"failed to load certificate");
+ BIO_free(bio);
+
+ dst->base = NULL;
+ dst->len = i2d_X509(cert, &dst->base);
+
+ X509_free(cert);
+}
+
+static void setup_sign_certificate(ptls_openssl_sign_certificate_t *sc)
+{
+ BIO *bio = BIO_new_mem_buf(RSA_PRIVATE_KEY, strlen(RSA_PRIVATE_KEY));
+ EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ assert(pkey != NULL || !"failed to load private key");
+ BIO_free(bio);
+
+ ptls_openssl_init_sign_certificate(sc, pkey);
+
+ EVP_PKEY_free(pkey);
+}
+
+int main(int argc, char **argv)
+{
+ ptls_openssl_sign_certificate_t openssl_sign_certificate;
+ ptls_openssl_verify_certificate_t openssl_verify_certificate;
+
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+#if !defined(OPENSSL_NO_ENGINE)
+ /* Load all compiled-in ENGINEs */
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_ciphers();
+ ENGINE_register_all_digests();
+#endif
+
+ ptls_iovec_t cert;
+ setup_certificate(&cert);
+ setup_sign_certificate(&openssl_sign_certificate);
+ ptls_openssl_init_verify_certificate(&openssl_verify_certificate, NULL);
+ ptls_context_t openssl_ctx = {ptls_openssl_random_bytes,
+ &ptls_get_time,
+ ptls_openssl_key_exchanges,
+ ptls_openssl_cipher_suites,
+ {&cert, 1},
+ NULL,
+ NULL,
+ &openssl_sign_certificate.super,
+ &openssl_verify_certificate.super};
+ assert(openssl_ctx.cipher_suites[0]->hash->digest_size == 48); /* sha384 */
+ ptls_context_t openssl_ctx_sha256only = openssl_ctx;
+ ++openssl_ctx_sha256only.cipher_suites;
+ assert(openssl_ctx_sha256only.cipher_suites[0]->hash->digest_size == 32); /* sha256 */
+
+ ctx = ctx_peer = &openssl_ctx;
+
+ subtest("ecdh-key-exchange", test_ecdh_key_exchange);
+ subtest("rsa-sign", test_rsa_sign);
+ subtest("ecdsa-sign", test_ecdsa_sign);
+ subtest("picotls", test_picotls);
+
+ ctx = ctx_peer = &openssl_ctx_sha256only;
+ subtest("picotls", test_picotls);
+
+ ctx = &openssl_ctx_sha256only;
+ ctx_peer = &openssl_ctx;
+ subtest("picotls", test_picotls);
+
+ ctx = &openssl_ctx;
+ ctx_peer = &openssl_ctx_sha256only;
+ subtest("picotls", test_picotls);
+
+ ptls_minicrypto_secp256r1sha256_sign_certificate_t minicrypto_sign_certificate;
+ ptls_iovec_t minicrypto_certificate = ptls_iovec_init(SECP256R1_CERTIFICATE, sizeof(SECP256R1_CERTIFICATE) - 1);
+ ptls_minicrypto_init_secp256r1sha256_sign_certificate(
+ &minicrypto_sign_certificate, ptls_iovec_init(SECP256R1_PRIVATE_KEY, sizeof(SECP256R1_PRIVATE_KEY) - 1));
+ ptls_context_t minicrypto_ctx = {ptls_minicrypto_random_bytes,
+ &ptls_get_time,
+ ptls_minicrypto_key_exchanges,
+ ptls_minicrypto_cipher_suites,
+ {&minicrypto_certificate, 1},
+ NULL,
+ NULL,
+ &minicrypto_sign_certificate.super};
+ ctx = &openssl_ctx;
+ ctx_peer = &minicrypto_ctx;
+ subtest("vs. minicrypto", test_picotls);
+
+ ctx = &minicrypto_ctx;
+ ctx_peer = &openssl_ctx;
+ subtest("minicrypto vs.", test_picotls);
+
+ return done_testing();
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/t/picotls.c b/web/server/h2o/libh2o/deps/picotls/t/picotls.c
new file mode 100644
index 00000000..bb90c62c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/t/picotls.c
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifdef _WINDOWS
+#include "wincompat.h"
+#endif
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include "picotls.h"
+#include "picotls/minicrypto.h"
+#include "../deps/picotest/picotest.h"
+#include "../lib/picotls.c"
+#include "test.h"
+
+ptls_context_t *ctx, *ctx_peer;
+
+static ptls_cipher_suite_t *find_cipher(ptls_context_t *ctx, uint16_t id)
+{
+ ptls_cipher_suite_t **cs;
+ for (cs = ctx->cipher_suites; *cs != NULL; ++cs)
+ if ((*cs)->id == id)
+ return *cs;
+ return NULL;
+}
+
+static void test_hash(ptls_hash_algorithm_t *hash)
+{
+ ptls_hash_context_t *hctx = hash->create();
+ uint8_t digest[PTLS_MAX_DIGEST_SIZE];
+
+ hctx->final(hctx, digest, PTLS_HASH_FINAL_MODE_FREE);
+ ok(memcmp(digest, hash->empty_digest, hash->digest_size) == 0);
+}
+
+static void test_sha256(void)
+{
+ test_hash(find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)->hash);
+}
+
+static void test_sha384(void)
+{
+ ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_256_GCM_SHA384);
+ if (cs != NULL)
+ test_hash(cs->hash);
+}
+
+static void test_hmac_sha256(void)
+{
+ /* test vector from RFC 4231 */
+ const char *secret = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", *message = "Hi There";
+ uint8_t digest[32];
+
+ ptls_hash_context_t *hctx =
+ ptls_hmac_create(find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)->hash, secret, strlen(secret));
+ hctx->update(hctx, message, strlen(message));
+ hctx->final(hctx, digest, 0);
+
+ ok(memcmp(digest, "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37"
+ "\x6c\x2e\x32\xcf\xf7",
+ 32) == 0);
+}
+
+static void test_hkdf(void)
+{
+ ptls_hash_algorithm_t *sha256 = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256)->hash;
+ const char salt[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c";
+ const char ikm[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+ const char info[] = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9";
+ uint8_t prk[PTLS_MAX_DIGEST_SIZE];
+ uint8_t okm[42];
+
+ ptls_hkdf_extract(sha256, prk, ptls_iovec_init(salt, sizeof(salt) - 1), ptls_iovec_init(ikm, sizeof(ikm) - 1));
+ ok(memcmp(prk, "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b\xba\x63\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84"
+ "\x4a\xd7\xc2\xb3\xe5",
+ 32) == 0);
+
+ ptls_hkdf_expand(sha256, okm, sizeof(okm), ptls_iovec_init(prk, sha256->digest_size), ptls_iovec_init(info, sizeof(info) - 1));
+ ok(memcmp(okm, "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36\x2f\x2a\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d"
+ "\x56\xec\xc4\xc5\xbf\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65",
+ sizeof(okm)) == 0);
+}
+
+static void test_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t *cs2)
+{
+ const char *traffic_secret = "01234567890123456789012345678901", *src1 = "hello world", *src2 = "good bye, all";
+ ptls_aead_context_t *c;
+ char enc1[256], enc2[256], dec1[256], dec2[256];
+ size_t enc1len, enc2len, dec1len, dec2len;
+
+ /* encrypt */
+ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL);
+ assert(c != NULL);
+ ptls_aead_encrypt_init(c, 0, NULL, 0);
+ enc1len = ptls_aead_encrypt_update(c, enc1, src1, strlen(src1));
+ enc1len += ptls_aead_encrypt_final(c, enc1 + enc1len);
+ ptls_aead_encrypt_init(c, 1, NULL, 0);
+ enc2len = ptls_aead_encrypt_update(c, enc2, src2, strlen(src2));
+ enc2len += ptls_aead_encrypt_final(c, enc2 + enc2len);
+ ptls_aead_free(c);
+
+ c = ptls_aead_new(cs2->aead, cs2->hash, 0, traffic_secret, NULL);
+ assert(c != NULL);
+
+ /* decrypt and compare */
+ dec1len = ptls_aead_decrypt(c, dec1, enc1, enc1len, 0, NULL, 0);
+ ok(dec1len != SIZE_MAX);
+ dec2len = ptls_aead_decrypt(c, dec2, enc2, enc2len, 1, NULL, 0);
+ ok(dec2len != SIZE_MAX);
+ ok(strlen(src1) == dec1len);
+ ok(memcmp(src1, dec1, dec1len) == 0);
+ ok(strlen(src2) == dec2len);
+ ok(memcmp(src2, dec2, dec2len - 1) == 0);
+
+ /* alter and decrypt to detect failure */
+ enc1[0] ^= 1;
+ dec1len = ptls_aead_decrypt(c, dec1, enc1, enc1len, 0, NULL, 0);
+ ok(dec1len == SIZE_MAX);
+
+ ptls_aead_free(c);
+}
+
+static void test_aad_ciphersuite(ptls_cipher_suite_t *cs1, ptls_cipher_suite_t *cs2)
+{
+ const char *traffic_secret = "01234567890123456789012345678901", *src = "hello world", *aad = "my true aad";
+ ptls_aead_context_t *c;
+ char enc[256], dec[256];
+ size_t enclen, declen;
+
+ /* encrypt */
+ c = ptls_aead_new(cs1->aead, cs1->hash, 1, traffic_secret, NULL);
+ assert(c != NULL);
+ ptls_aead_encrypt_init(c, 123, aad, strlen(aad));
+ enclen = ptls_aead_encrypt_update(c, enc, src, strlen(src));
+ enclen += ptls_aead_encrypt_final(c, enc + enclen);
+ ptls_aead_free(c);
+
+ /* decrypt */
+ c = ptls_aead_new(cs2->aead, cs2->hash, 0, traffic_secret, NULL);
+ assert(c != NULL);
+ declen = ptls_aead_decrypt(c, dec, enc, enclen, 123, aad, strlen(aad));
+ ok(declen == strlen(src));
+ ok(memcmp(src, dec, declen) == 0);
+ declen = ptls_aead_decrypt(c, dec, enc, enclen, 123, "my fake aad", strlen(aad));
+ ok(declen == SIZE_MAX);
+ ptls_aead_free(c);
+}
+
+static void test_ctr(ptls_cipher_suite_t *cs, const uint8_t *key, size_t key_len, const void *iv, size_t iv_len,
+ const void *expected, size_t expected_len)
+{
+ static uint8_t zeroes[64] = {0};
+
+ if (cs == NULL)
+ return;
+
+ ptls_cipher_algorithm_t *algo = cs->aead->ctr_cipher;
+ uint8_t buf[sizeof(zeroes)];
+
+ assert(expected_len <= sizeof(zeroes));
+ ok(algo->key_size == key_len);
+ ok(algo->iv_size == iv_len);
+
+ ptls_cipher_context_t *ctx = ptls_cipher_new(algo, 1, key);
+ assert(ctx != NULL);
+ ptls_cipher_init(ctx, iv);
+ ptls_cipher_encrypt(ctx, buf, zeroes, expected_len);
+ ptls_cipher_free(ctx);
+
+ ok(memcmp(buf, expected, expected_len) == 0);
+}
+
+static void test_aes128ctr(void)
+{
+ static const uint8_t key[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c},
+ iv[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
+ expected[] = {0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60,
+ 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97};
+
+ test_ctr(find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256), key, sizeof(key), iv, sizeof(iv), expected, sizeof(expected));
+}
+
+static void test_chacha20(void)
+{
+ static const uint8_t key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+ iv[] = {1, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0x4a, 0, 0, 0, 0},
+ expected[] = {0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, 0x50, 0x0f, 0xdd,
+ 0x1f, 0xa3, 0x20, 0x71, 0xc4, 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0,
+ 0x68, 0x03, 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e};
+
+ test_ctr(find_cipher(ctx, PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256), key, sizeof(key), iv, sizeof(iv), expected,
+ sizeof(expected));
+}
+
+static void test_aes128gcm(void)
+{
+ ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256),
+ *cs_peer = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_128_GCM_SHA256);
+
+ test_ciphersuite(cs, cs_peer);
+ test_aad_ciphersuite(cs, cs_peer);
+}
+
+static void test_aes256gcm(void)
+{
+ ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_256_GCM_SHA384),
+ *cs_peer = find_cipher(ctx, PTLS_CIPHER_SUITE_AES_256_GCM_SHA384);
+
+ if (cs != NULL && cs_peer != NULL) {
+ test_ciphersuite(cs, cs_peer);
+ test_aad_ciphersuite(cs, cs_peer);
+ }
+}
+
+static void test_chacha20poly1305(void)
+{
+ ptls_cipher_suite_t *cs = find_cipher(ctx, PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256),
+ *cs_peer = find_cipher(ctx, PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256);
+
+ if (cs != NULL && cs_peer != NULL) {
+ test_ciphersuite(cs, cs_peer);
+ test_aad_ciphersuite(cs, cs_peer);
+ }
+}
+
+static struct {
+ struct {
+ uint8_t buf[32];
+ size_t len;
+ int is_end_of_record;
+ } vec[16];
+ size_t count;
+} test_fragmented_message_queue = {{{{0}}}};
+
+static int test_fragmented_message_record(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t message, int is_end_of_record,
+ ptls_handshake_properties_t *properties)
+{
+ memcpy(test_fragmented_message_queue.vec[test_fragmented_message_queue.count].buf, message.base, message.len);
+ test_fragmented_message_queue.vec[test_fragmented_message_queue.count].len = message.len;
+ test_fragmented_message_queue.vec[test_fragmented_message_queue.count].is_end_of_record = is_end_of_record;
+ ++test_fragmented_message_queue.count;
+
+ return 0;
+}
+
+static void test_fragmented_message(void)
+{
+ ptls_t tls = {NULL};
+ struct st_ptls_record_t rec = {PTLS_CONTENT_TYPE_HANDSHAKE, 0x0301};
+ int ret;
+
+#define SET_RECORD(lit) \
+ do { \
+ rec.length = sizeof(lit) - 1; \
+ rec.fragment = (const uint8_t *)(lit); \
+ } while (0)
+
+ /* not fragmented */
+ test_fragmented_message_queue.count = 0;
+ SET_RECORD("\x01\x00\x00\x03"
+ "abc");
+ ret = handle_handshake_record(&tls, test_fragmented_message_record, NULL, &rec, NULL);
+ ok(ret == 0);
+ ok(test_fragmented_message_queue.count == 1);
+ ok(test_fragmented_message_queue.vec[0].len == rec.length);
+ ok(memcmp(test_fragmented_message_queue.vec[0].buf, rec.fragment, rec.length) == 0);
+ ok(test_fragmented_message_queue.vec[0].is_end_of_record);
+ ok(tls.recvbuf.mess.base == NULL);
+
+ /* fragmented */
+ test_fragmented_message_queue.count = 0;
+ SET_RECORD("\x01\x00\x00\x03"
+ "a");
+ ret = handle_handshake_record(&tls, test_fragmented_message_record, NULL, &rec, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(tls.recvbuf.mess.base != NULL);
+ ok(test_fragmented_message_queue.count == 0);
+ SET_RECORD("bc\x02\x00\x00\x02"
+ "de"
+ "\x03");
+ ret = handle_handshake_record(&tls, test_fragmented_message_record, NULL, &rec, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(test_fragmented_message_queue.count == 2);
+ ok(test_fragmented_message_queue.vec[0].len == 7);
+ ok(memcmp(test_fragmented_message_queue.vec[0].buf, "\x01\x00\x00\x03"
+ "abc",
+ 7) == 0);
+ ok(!test_fragmented_message_queue.vec[0].is_end_of_record);
+ ok(test_fragmented_message_queue.vec[1].len == 6);
+ ok(memcmp(test_fragmented_message_queue.vec[1].buf, "\x02\x00\x00\x02"
+ "de",
+ 6) == 0);
+ ok(!test_fragmented_message_queue.vec[1].is_end_of_record);
+ SET_RECORD("\x00\x00\x03"
+ "end");
+ ret = handle_handshake_record(&tls, test_fragmented_message_record, NULL, &rec, NULL);
+ ok(ret == 0);
+ ok(tls.recvbuf.mess.base == NULL);
+ ok(test_fragmented_message_queue.count == 3);
+ ok(test_fragmented_message_queue.vec[2].len == 7);
+ ok(memcmp(test_fragmented_message_queue.vec[2].buf, "\x03\x00\x00\x03"
+ "end",
+ 7) == 0);
+ ok(test_fragmented_message_queue.vec[2].is_end_of_record);
+
+#undef SET_RECORD
+}
+
+static int save_client_hello(ptls_on_client_hello_t *self, ptls_t *tls, ptls_iovec_t server_name, const ptls_iovec_t *protocols,
+ size_t num_protocols, const uint16_t *signature_algorithms, size_t num_signature_algorithms)
+{
+ ptls_set_server_name(tls, (const char *)server_name.base, server_name.len);
+ ptls_set_negotiated_protocol(tls, (const char *)protocols[0].base, protocols[0].len);
+ return 0;
+}
+
+enum { TEST_HANDSHAKE_1RTT, TEST_HANDSHAKE_2RTT, TEST_HANDSHAKE_HRR, TEST_HANDSHAKE_HRR_STATELESS, TEST_HANDSHAKE_EARLY_DATA };
+
+static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch)
+{
+ ptls_t *client, *server;
+ ptls_handshake_properties_t client_hs_prop = {{{{NULL}, ticket}}}, server_hs_prop = {{{{NULL}}}};
+ uint8_t cbuf_small[16384], sbuf_small[16384], decbuf_small[16384];
+ ptls_buffer_t cbuf, sbuf, decbuf;
+ size_t consumed, max_early_data_size = 0;
+ int ret;
+ const char *req = "GET / HTTP/1.0\r\n\r\n";
+ const char *resp = "HTTP/1.0 200 OK\r\n\r\nhello world\n";
+
+ client = ptls_new(ctx, 0);
+ server = ptls_new(ctx_peer, 1);
+ ptls_buffer_init(&cbuf, cbuf_small, sizeof(cbuf_small));
+ ptls_buffer_init(&sbuf, sbuf_small, sizeof(sbuf_small));
+ ptls_buffer_init(&decbuf, decbuf_small, sizeof(decbuf_small));
+
+ if (check_ch) {
+ static ptls_on_client_hello_t cb = {save_client_hello};
+ ctx_peer->on_client_hello = &cb;
+ static const ptls_iovec_t protocols[] = {{(uint8_t *)"h2", 2}, {(uint8_t *)"http/1.1", 8}};
+ client_hs_prop.client.negotiated_protocols.list = protocols;
+ client_hs_prop.client.negotiated_protocols.count = sizeof(protocols) / sizeof(protocols[0]);
+ ptls_set_server_name(client, "example.com", 0);
+ }
+
+ switch (mode) {
+ case TEST_HANDSHAKE_HRR:
+ client_hs_prop.client.negotiate_before_key_exchange = 1;
+ break;
+ case TEST_HANDSHAKE_HRR_STATELESS:
+ client_hs_prop.client.negotiate_before_key_exchange = 1;
+ server_hs_prop.server.cookie.key = "0123456789abcdef0123456789abcdef";
+ server_hs_prop.server.retry_uses_cookie = 1;
+ break;
+ case TEST_HANDSHAKE_EARLY_DATA:
+ assert(ctx_peer->max_early_data_size != 0);
+ client_hs_prop.client.max_early_data_size = &max_early_data_size;
+ break;
+ }
+
+ ret = ptls_handshake(client, &cbuf, NULL, NULL, &client_hs_prop);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(cbuf.off != 0);
+
+ switch (mode) {
+ case TEST_HANDSHAKE_2RTT:
+ case TEST_HANDSHAKE_HRR:
+ case TEST_HANDSHAKE_HRR_STATELESS:
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, &server_hs_prop);
+ if (mode == TEST_HANDSHAKE_HRR_STATELESS) {
+ ok(ret == PTLS_ERROR_STATELESS_RETRY);
+ ptls_free(server);
+ server = ptls_new(ctx_peer, 1);
+ } else {
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ }
+ ok(cbuf.off == consumed);
+ ok(sbuf.off != 0);
+ cbuf.off = 0;
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, &client_hs_prop);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(sbuf.off == consumed);
+ ok(cbuf.off != 0);
+ sbuf.off = 0;
+ break;
+ case TEST_HANDSHAKE_EARLY_DATA:
+ ok(max_early_data_size == ctx_peer->max_early_data_size);
+ ret = ptls_send(client, &cbuf, req, strlen(req));
+ ok(ret == 0);
+ break;
+ }
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, &server_hs_prop);
+ ok(ret == 0);
+ ok(sbuf.off != 0);
+ if (check_ch) {
+ ok(ptls_get_server_name(server) != NULL);
+ ok(strcmp(ptls_get_server_name(server), "example.com") == 0);
+ ok(ptls_get_negotiated_protocol(server) != NULL);
+ ok(strcmp(ptls_get_negotiated_protocol(server), "h2") == 0);
+ } else {
+ ok(ptls_get_server_name(server) == NULL);
+ ok(ptls_get_negotiated_protocol(server) == NULL);
+ }
+
+ if (mode == TEST_HANDSHAKE_EARLY_DATA) {
+ ok(consumed < cbuf.off);
+ memmove(cbuf.base, cbuf.base + consumed, cbuf.off - consumed);
+ cbuf.off -= consumed;
+
+ consumed = cbuf.off;
+ ret = ptls_receive(server, &decbuf, cbuf.base, &consumed);
+ ok(ret == 0);
+ ok(consumed == cbuf.off);
+ ok(decbuf.off == strlen(req));
+ ok(memcmp(decbuf.base, req, decbuf.off) == 0);
+ ok(!ptls_handshake_is_complete(server));
+ cbuf.off = 0;
+ decbuf.off = 0;
+
+ ret = ptls_send(server, &sbuf, resp, strlen(resp));
+ ok(ret == 0);
+ } else {
+ ok(consumed == cbuf.off);
+ cbuf.off = 0;
+ }
+
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, NULL);
+ ok(ret == 0);
+ ok(cbuf.off != 0);
+ if (check_ch) {
+ ok(ptls_get_server_name(client) != NULL);
+ ok(strcmp(ptls_get_server_name(client), "example.com") == 0);
+ ok(ptls_get_negotiated_protocol(client) != NULL);
+ ok(strcmp(ptls_get_negotiated_protocol(client), "h2") == 0);
+ } else {
+ ok(ptls_get_server_name(server) == NULL);
+ ok(ptls_get_negotiated_protocol(server) == NULL);
+ }
+
+ if (expect_ticket) {
+ ok(consumed < sbuf.off);
+ memmove(sbuf.base, sbuf.base + consumed, sbuf.off - consumed);
+ sbuf.off -= consumed;
+ } else {
+ ok(consumed == sbuf.off);
+ sbuf.off = 0;
+ }
+
+ if (mode != TEST_HANDSHAKE_EARLY_DATA) {
+ ret = ptls_send(client, &cbuf, req, strlen(req));
+ ok(ret == 0);
+
+ consumed = cbuf.off;
+ ret = ptls_receive(server, &decbuf, cbuf.base, &consumed);
+ ok(ret == 0);
+ ok(consumed == cbuf.off);
+ ok(decbuf.off == strlen(req));
+ ok(memcmp(decbuf.base, req, strlen(req)) == 0);
+ ok(ptls_handshake_is_complete(server));
+ decbuf.off = 0;
+
+ ret = ptls_send(server, &sbuf, resp, strlen(resp));
+ ok(ret == 0);
+ }
+
+ consumed = sbuf.off;
+ ret = ptls_receive(client, &decbuf, sbuf.base, &consumed);
+ ok(ret == 0);
+ ok(consumed == sbuf.off);
+ ok(decbuf.off == strlen(resp));
+ ok(memcmp(decbuf.base, resp, strlen(resp)) == 0);
+ ok(ptls_handshake_is_complete(client));
+ decbuf.off = 0;
+
+ if (mode == TEST_HANDSHAKE_EARLY_DATA) {
+ consumed = cbuf.off;
+ ret = ptls_receive(server, &decbuf, cbuf.base, &consumed);
+ ok(ret == 0);
+ ok(cbuf.off == consumed);
+ ok(decbuf.off == 0);
+ ok(ptls_handshake_is_complete(client));
+ }
+
+ ptls_buffer_dispose(&cbuf);
+ ptls_buffer_dispose(&sbuf);
+ ptls_buffer_dispose(&decbuf);
+ ptls_free(client);
+ ptls_free(server);
+
+ if (check_ch)
+ ctx_peer->on_client_hello = NULL;
+}
+
+static ptls_sign_certificate_t *sc_orig;
+size_t sc_callcnt;
+
+static int sign_certificate(ptls_sign_certificate_t *self, ptls_t *tls, uint16_t *selected_algorithm, ptls_buffer_t *output,
+ ptls_iovec_t input, const uint16_t *algorithms, size_t num_algorithms)
+{
+ ++sc_callcnt;
+ return sc_orig->cb(sc_orig, tls, selected_algorithm, output, input, algorithms, num_algorithms);
+}
+
+static void test_full_handshake(void)
+{
+ sc_callcnt = 0;
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0);
+ ok(sc_callcnt == 1);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0);
+ ok(sc_callcnt == 2);
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1);
+ ok(sc_callcnt == 3);
+}
+
+static void test_hrr_handshake(void)
+{
+ sc_callcnt = 0;
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0);
+ ok(sc_callcnt == 1);
+}
+
+static void test_hrr_stateless_handshake(void)
+{
+ sc_callcnt = 0;
+ test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0);
+ ok(sc_callcnt == 1);
+}
+
+static int copy_ticket(ptls_encrypt_ticket_t *self, ptls_t *tls, int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src)
+{
+ int ret;
+
+ if ((ret = ptls_buffer_reserve(dst, src.len)) != 0)
+ return ret;
+ memcpy(dst->base + dst->off, src.base, src.len);
+ dst->off += src.len;
+
+ return 0;
+}
+
+static ptls_iovec_t saved_ticket = {NULL};
+
+static int save_ticket(ptls_save_ticket_t *self, ptls_t *tls, ptls_iovec_t src)
+{
+ saved_ticket.base = malloc(src.len);
+ memcpy(saved_ticket.base, src.base, src.len);
+ saved_ticket.len = src.len;
+ return 0;
+}
+
+static void do_test_resumption(int different_preferred_key_share)
+{
+ assert(ctx->key_exchanges[0]->id == ctx_peer->key_exchanges[0]->id);
+ assert(ctx->key_exchanges[1] == NULL);
+ assert(ctx_peer->key_exchanges[1] == NULL);
+ assert(ctx->key_exchanges[0]->id != ptls_minicrypto_x25519.id);
+ ptls_key_exchange_algorithm_t *different_key_exchanges[] = {&ptls_minicrypto_x25519, ctx->key_exchanges[0], NULL},
+ **key_exchanges_orig = ctx->key_exchanges;
+
+ if (different_preferred_key_share)
+ ctx->key_exchanges = different_key_exchanges;
+
+ ptls_encrypt_ticket_t et = {copy_ticket};
+ ptls_save_ticket_t st = {save_ticket};
+
+ assert(ctx_peer->ticket_lifetime == 0);
+ assert(ctx_peer->max_early_data_size == 0);
+ assert(ctx_peer->encrypt_ticket == NULL);
+ assert(ctx_peer->save_ticket == NULL);
+ saved_ticket = ptls_iovec_init(NULL, 0);
+
+ ctx_peer->ticket_lifetime = 86400;
+ ctx_peer->max_early_data_size = 8192;
+ ctx_peer->encrypt_ticket = &et;
+ ctx->save_ticket = &st;
+
+ sc_callcnt = 0;
+ test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0);
+ ok(sc_callcnt == 1);
+ ok(saved_ticket.base != NULL);
+
+ /* psk using saved ticket */
+ test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0);
+ ok(sc_callcnt == 1);
+
+ /* 0-rtt psk using saved ticket */
+ test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0);
+ ok(sc_callcnt == 1);
+
+ ctx->require_dhe_on_psk = 1;
+
+ /* psk-dhe using saved ticket */
+ test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0);
+ ok(sc_callcnt == 1);
+
+ /* 0-rtt psk-dhe using saved ticket */
+ test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0);
+ ok(sc_callcnt == 1);
+
+ ctx->require_dhe_on_psk = 0;
+ ctx_peer->ticket_lifetime = 0;
+ ctx_peer->max_early_data_size = 0;
+ ctx_peer->encrypt_ticket = NULL;
+ ctx->save_ticket = NULL;
+ ctx->key_exchanges = key_exchanges_orig;
+}
+
+static void test_resumption(void)
+{
+ do_test_resumption(0);
+}
+
+static void test_resumption_different_preferred_key_share(void)
+{
+ if (ctx == ctx_peer)
+ return;
+ do_test_resumption(1);
+}
+
+static void test_enforce_retry(int use_cookie)
+{
+ ptls_t *client, *server;
+ ptls_handshake_properties_t server_hs_prop = {{{{NULL}}}};
+ ptls_buffer_t cbuf, sbuf, decbuf;
+ size_t consumed;
+ int ret;
+
+ server_hs_prop.server.cookie.key = "0123456789abcdef0123456789abcdef";
+ server_hs_prop.server.cookie.additional_data = ptls_iovec_init("1.2.3.4:1234", 12);
+ server_hs_prop.server.enforce_retry = 1;
+ server_hs_prop.server.retry_uses_cookie = use_cookie;
+
+ ptls_buffer_init(&cbuf, "", 0);
+ ptls_buffer_init(&sbuf, "", 0);
+ ptls_buffer_init(&decbuf, "", 0);
+
+ client = ptls_new(ctx, 0);
+
+ ret = ptls_handshake(client, &cbuf, NULL, NULL, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(cbuf.off != 0);
+
+ server = ptls_new(ctx, 1);
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, &server_hs_prop);
+ cbuf.off = 0;
+
+ if (use_cookie) {
+ ok(ret == PTLS_ERROR_STATELESS_RETRY);
+ ptls_free(server);
+ server = ptls_new(ctx, 1);
+ } else {
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ }
+
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(sbuf.off == consumed);
+ sbuf.off = 0;
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, &server_hs_prop);
+ ok(ret == 0);
+ ok(cbuf.off == consumed);
+ cbuf.off = 0;
+
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, NULL);
+ ok(ret == 0);
+ ok(sbuf.off == consumed);
+ sbuf.off = 0;
+
+ ret = ptls_send(client, &cbuf, "hello world", 11);
+ ok(ret == 0);
+
+ consumed = cbuf.off;
+ ret = ptls_receive(server, &decbuf, cbuf.base, &consumed);
+ ok(ret == 0);
+ ok(cbuf.off == consumed);
+ cbuf.off = 0;
+
+ ok(decbuf.off == 11);
+ ok(memcmp(decbuf.base, "hello world", 11) == 0);
+ decbuf.off = 0;
+
+ ptls_free(client);
+ ptls_free(server);
+
+ ptls_buffer_dispose(&cbuf);
+ ptls_buffer_dispose(&sbuf);
+ ptls_buffer_dispose(&decbuf);
+}
+
+static void test_enforce_retry_stateful(void)
+{
+ test_enforce_retry(0);
+}
+
+static void test_enforce_retry_stateless(void)
+{
+ test_enforce_retry(1);
+}
+
+static ptls_t *stateless_hrr_prepare(ptls_buffer_t *sbuf, ptls_handshake_properties_t *server_hs_prop)
+{
+ ptls_t *client = ptls_new(ctx, 0), *server = ptls_new(ctx_peer, 1);
+ ptls_buffer_t cbuf;
+ size_t consumed;
+ int ret;
+
+ ptls_buffer_init(&cbuf, "", 0);
+ ptls_buffer_init(sbuf, "", 0);
+
+ ret = ptls_handshake(client, &cbuf, NULL, NULL, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, sbuf, cbuf.base, &consumed, server_hs_prop);
+ ok(ret == PTLS_ERROR_STATELESS_RETRY);
+
+ ptls_buffer_dispose(&cbuf);
+ ptls_free(server);
+
+ return client;
+}
+
+static void test_stateless_hrr_aad_change(void)
+{
+ ptls_t *client, *server;
+ ptls_handshake_properties_t server_hs_prop = {{{{NULL}}}};
+ ptls_buffer_t cbuf, sbuf;
+ size_t consumed;
+ int ret;
+
+ server_hs_prop.server.cookie.key = "0123456789abcdef0123456789abcdef";
+ server_hs_prop.server.cookie.additional_data = ptls_iovec_init("1.2.3.4:1234", 12);
+ server_hs_prop.server.enforce_retry = 1;
+ server_hs_prop.server.retry_uses_cookie = 1;
+
+ client = stateless_hrr_prepare(&sbuf, &server_hs_prop);
+ ptls_buffer_init(&cbuf, "", 0);
+
+ consumed = sbuf.off;
+ ret = ptls_handshake(client, &cbuf, sbuf.base, &consumed, NULL);
+ ok(ret == PTLS_ERROR_IN_PROGRESS);
+ ok(sbuf.off == consumed);
+ sbuf.off = 0;
+
+ server = ptls_new(ctx_peer, 1);
+ server_hs_prop.server.cookie.additional_data = ptls_iovec_init("1.2.3.4:4321", 12);
+
+ consumed = cbuf.off;
+ ret = ptls_handshake(server, &sbuf, cbuf.base, &consumed, &server_hs_prop);
+ ok(ret == PTLS_ALERT_HANDSHAKE_FAILURE);
+
+ ptls_free(client);
+ ptls_free(server);
+
+ ptls_buffer_dispose(&cbuf);
+ ptls_buffer_dispose(&sbuf);
+}
+
+void test_picotls(void)
+{
+ subtest("sha256", test_sha256);
+ subtest("sha384", test_sha384);
+ subtest("hmac-sha256", test_hmac_sha256);
+ subtest("hkdf", test_hkdf);
+ subtest("aes128gcm", test_aes128gcm);
+ subtest("aes256gcm", test_aes256gcm);
+ subtest("chacha20poly1305", test_chacha20poly1305);
+ subtest("aes128ctr", test_aes128ctr);
+ subtest("chacha20", test_chacha20);
+
+ subtest("fragmented-message", test_fragmented_message);
+
+ ptls_sign_certificate_t sc = {sign_certificate};
+ sc_orig = ctx_peer->sign_certificate;
+ ctx_peer->sign_certificate = &sc;
+
+ subtest("full-handshake", test_full_handshake);
+ subtest("hrr-handshake", test_hrr_handshake);
+ subtest("hrr-stateless-handshake", test_hrr_stateless_handshake);
+ subtest("resumption", test_resumption);
+ subtest("resumption-different-preferred-key-share", test_resumption_different_preferred_key_share);
+
+ subtest("enforce-retry-stateful", test_enforce_retry_stateful);
+ subtest("enforce-retry-stateless", test_enforce_retry_stateless);
+
+ subtest("stateless-hrr-aad-change", test_stateless_hrr_aad_change);
+
+ ctx_peer->sign_certificate = sc_orig;
+}
+
+void test_key_exchange(ptls_key_exchange_algorithm_t *algo)
+{
+ ptls_key_exchange_context_t *ctx;
+ ptls_iovec_t client_pubkey, client_secret, server_pubkey, server_secret;
+ int ret;
+
+ /* fail */
+ ret = algo->exchange(&server_pubkey, &server_secret, (ptls_iovec_t){NULL});
+ ok(ret != 0);
+
+ /* perform ecdh */
+ ret = algo->create(&ctx, &client_pubkey);
+ ok(ret == 0);
+ ret = algo->exchange(&server_pubkey, &server_secret, client_pubkey);
+ ok(ret == 0);
+ ret = ctx->on_exchange(&ctx, &client_secret, server_pubkey);
+ ok(ret == 0);
+ ok(client_secret.len == server_secret.len);
+ ok(memcmp(client_secret.base, server_secret.base, client_secret.len) == 0);
+
+ free(client_secret.base);
+ free(server_pubkey.base);
+ free(server_secret.base);
+}
diff --git a/web/server/h2o/libh2o/deps/picotls/t/test.h b/web/server/h2o/libh2o/deps/picotls/t/test.h
new file mode 100644
index 00000000..2f338764
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/t/test.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 DeNA Co., Ltd., Kazuho Oku
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef test_h
+#define test_h
+
+#include "picotls.h"
+
+/* raw private key and certificate using secp256v1 */
+#define SECP256R1_PRIVATE_KEY \
+ "\x92\xbe\xc7\x34\x58\xc8\xa7\x1a\x25\x22\xf0\x29\x81\xc8\xca\x33\x84\xa5\xca\x0b\x8f\x0f\x19\x94\x83\xcb\xaf\x3f\x3d\x9f\x19" \
+ "\xa1"
+#define SECP256R1_CERTIFICATE \
+ "\x30\x82\x01\x97\x30\x82\x01\x3f\xa0\x03\x02\x01\x02\x02\x09\x00\xa5\x28\xf1\x53\xe1\x92\xb8\x1c\x30\x09\x06\x07\x2a\x86\x48" \
+ "\xce\x3d\x04\x01\x30\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x1e\x17" \
+ "\x0d\x31\x36\x31\x31\x30\x33\x30\x37\x31\x33\x32\x39\x5a\x17\x0d\x32\x36\x31\x31\x30\x31\x30\x37\x31\x33\x32\x39\x5a\x30\x16" \
+ "\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07\x2a\x86\x48" \
+ "\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x73\x47\xc4\x07\x56\x9a\x5a\x83\xa2\x49\xba\x34\x73" \
+ "\x66\xd8\xb5\x95\x1e\xd6\xe9\x4e\xaf\x76\x09\x9f\x96\xb6\xb6\xab\xd3\xb9\xf0\x3e\x96\x10\x6f\xb2\xb4\x42\x93\x95\xfc\x30\x61" \
+ "\x3b\xb4\x4b\xa1\x46\x92\xec\xf9\xf1\x0f\x7a\x25\x5c\x87\x29\x3e\x23\x56\x77\x91\xa3\x77\x30\x75\x30\x1d\x06\x03\x55\x1d\x0e" \
+ "\x04\x16\x04\x14\x24\x7a\x07\x7b\x93\xd2\x3a\x60\x5e\xea\xb3\xdf\x21\xdf\x02\x63\x7d\x89\x40\xdd\x30\x46\x06\x03\x55\x1d\x23" \
+ "\x04\x3f\x30\x3d\x80\x14\x24\x7a\x07\x7b\x93\xd2\x3a\x60\x5e\xea\xb3\xdf\x21\xdf\x02\x63\x7d\x89\x40\xdd\xa1\x1a\xa4\x18\x30" \
+ "\x16\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d\x82\x09\x00\xa5\x28\xf1\x53\xe1" \
+ "\x92\xb8\x1c\x30\x0c\x06\x03\x55\x1d\x13\x04\x05\x30\x03\x01\x01\xff\x30\x09\x06\x07\x2a\x86\x48\xce\x3d\x04\x01\x03\x47\x00" \
+ "\x30\x44\x02\x20\x3f\xfc\x14\x45\xa4\xc6\x21\x37\xa9\x4a\x6b\x79\x4d\x86\xea\x48\x2c\xa8\xea\xb8\x18\xd9\xc9\x94\xd0\x15\x38" \
+ "\xa5\xfd\x23\xf1\xb0\x02\x20\x2e\xd4\x93\xfe\x19\xfa\x31\x82\xa0\xfe\xa2\x04\xbd\xf4\x8b\x68\xdb\xee\x7a\xe8\x33\x2c\xe1\x35" \
+ "\x6d\xdc\x08\x37\xfd\x49\x35\x90"
+
+extern ptls_context_t *ctx, *ctx_peer;
+
+void test_key_exchange(ptls_key_exchange_algorithm_t *algo);
+void test_picotls(void);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/picotls/t/util.h b/web/server/h2o/libh2o/deps/picotls/t/util.h
new file mode 100644
index 00000000..78ce87c3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/picotls/t/util.h
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2016,2017 DeNA Co., Ltd., Kazuho Oku, Fastly
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef util_h
+#define util_h
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */
+#endif
+
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <openssl/pem.h>
+#include "picotls/openssl.h"
+
+static inline void load_certificate_chain(ptls_context_t *ctx, const char *fn)
+{
+ if (ptls_load_certificates(ctx, (char *)fn) != 0) {
+ fprintf(stderr, "failed to load certificate:%s:%s\n", fn, strerror(errno));
+ exit(1);
+ }
+}
+
+static inline void load_private_key(ptls_context_t *ctx, const char *fn)
+{
+ static ptls_openssl_sign_certificate_t sc;
+ FILE *fp;
+ EVP_PKEY *pkey;
+
+ if ((fp = fopen(fn, "rb")) == NULL) {
+ fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno));
+ exit(1);
+ }
+ pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+ fclose(fp);
+
+ if (pkey == NULL) {
+ fprintf(stderr, "failed to read private key from file:%s\n", fn);
+ exit(1);
+ }
+
+ ptls_openssl_init_sign_certificate(&sc, pkey);
+ EVP_PKEY_free(pkey);
+
+ ctx->sign_certificate = &sc.super;
+}
+
+struct st_util_save_ticket_t {
+ ptls_save_ticket_t super;
+ char fn[MAXPATHLEN];
+};
+
+static int save_ticket_cb(ptls_save_ticket_t *_self, ptls_t *tls, ptls_iovec_t src)
+{
+ struct st_util_save_ticket_t *self = (void *)_self;
+ FILE *fp;
+
+ if ((fp = fopen(self->fn, "wb")) == NULL) {
+ fprintf(stderr, "failed to open file:%s:%s\n", self->fn, strerror(errno));
+ return PTLS_ERROR_LIBRARY;
+ }
+ fwrite(src.base, 1, src.len, fp);
+ fclose(fp);
+
+ return 0;
+}
+
+static inline void setup_session_file(ptls_context_t *ctx, ptls_handshake_properties_t *hsprop, const char *fn)
+{
+ static struct st_util_save_ticket_t st;
+ FILE *fp;
+
+ /* setup save_ticket callback */
+ strcpy(st.fn, fn);
+ st.super.cb = save_ticket_cb;
+ ctx->save_ticket = &st.super;
+
+ /* load session ticket if possible */
+ if ((fp = fopen(fn, "rb")) != NULL) {
+ static uint8_t ticket[16384];
+ size_t ticket_size = fread(ticket, 1, sizeof(ticket), fp);
+ if (ticket_size == 0 || !feof(fp)) {
+ fprintf(stderr, "failed to load ticket from file:%s\n", fn);
+ exit(1);
+ }
+ fclose(fp);
+ hsprop->client.session_ticket = ptls_iovec_init(ticket, ticket_size);
+ }
+}
+
+static inline void setup_verify_certificate(ptls_context_t *ctx)
+{
+ static ptls_openssl_verify_certificate_t vc;
+ ptls_openssl_init_verify_certificate(&vc, NULL);
+ ctx->verify_certificate = &vc.super;
+}
+
+struct st_util_log_secret_t {
+ ptls_log_secret_t super;
+ FILE *fp;
+};
+
+static void fprinthex(FILE *fp, ptls_iovec_t vec)
+{
+ size_t i;
+ for (i = 0; i != vec.len; ++i)
+ fprintf(fp, "%02x", vec.base[i]);
+}
+
+static void log_secret_cb(ptls_log_secret_t *_self, ptls_t *tls, const char *label, ptls_iovec_t secret)
+{
+ struct st_util_log_secret_t *self = (void *)_self;
+
+ fprintf(self->fp, "%s ", label);
+ fprinthex(self->fp, ptls_get_client_random(tls));
+ fprintf(self->fp, " ");
+ fprinthex(self->fp, secret);
+ fprintf(self->fp, "\n");
+ fflush(self->fp);
+}
+
+static inline void setup_log_secret(ptls_context_t *ctx, const char *fn)
+{
+ static struct st_util_log_secret_t ls;
+
+ if ((ls.fp = fopen(fn, "at")) == NULL) {
+ fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno));
+ exit(1);
+ }
+ ls.super.cb = log_secret_cb;
+ ctx->log_secret = &ls.super;
+}
+
+/* single-entry session cache */
+struct st_util_session_cache_t {
+ ptls_encrypt_ticket_t super;
+ uint8_t id[32];
+ ptls_iovec_t data;
+};
+
+static int encrypt_ticket_cb(ptls_encrypt_ticket_t *_self, ptls_t *tls, int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src)
+{
+ struct st_util_session_cache_t *self = (void *)_self;
+ int ret;
+
+ if (is_encrypt) {
+
+ /* replace the cached entry along with a newly generated session id */
+ free(self->data.base);
+ if ((self->data.base = malloc(src.len)) == NULL)
+ return PTLS_ERROR_NO_MEMORY;
+
+ ptls_get_context(tls)->random_bytes(self->id, sizeof(self->id));
+ memcpy(self->data.base, src.base, src.len);
+ self->data.len = src.len;
+
+ /* store the session id in buffer */
+ if ((ret = ptls_buffer_reserve(dst, sizeof(self->id))) != 0)
+ return ret;
+ memcpy(dst->base + dst->off, self->id, sizeof(self->id));
+ dst->off += sizeof(self->id);
+
+ } else {
+
+ /* check if session id is the one stored in cache */
+ if (src.len != sizeof(self->id))
+ return PTLS_ERROR_SESSION_NOT_FOUND;
+ if (memcmp(self->id, src.base, sizeof(self->id)) != 0)
+ return PTLS_ERROR_SESSION_NOT_FOUND;
+
+ /* return the cached value */
+ if ((ret = ptls_buffer_reserve(dst, self->data.len)) != 0)
+ return ret;
+ memcpy(dst->base + dst->off, self->data.base, self->data.len);
+ dst->off += self->data.len;
+ }
+
+ return 0;
+}
+
+static inline void setup_session_cache(ptls_context_t *ctx)
+{
+ static struct st_util_session_cache_t sc;
+
+ sc.super.cb = encrypt_ticket_cb;
+
+ ctx->ticket_lifetime = 86400;
+ ctx->max_early_data_size = 8192;
+ ctx->encrypt_ticket = &sc.super;
+}
+
+static inline int resolve_address(struct sockaddr *sa, socklen_t *salen, const char *host, const char *port, int family, int type,
+ int proto)
+{
+ struct addrinfo hints, *res;
+ int err;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = type;
+ hints.ai_protocol = proto;
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE;
+ if ((err = getaddrinfo(host, port, &hints, &res)) != 0 || res == NULL) {
+ fprintf(stderr, "failed to resolve address:%s:%s:%s\n", host, port,
+ err != 0 ? gai_strerror(err) : "getaddrinfo returned NULL");
+ return -1;
+ }
+
+ memcpy(sa, res->ai_addr, res->ai_addrlen);
+ *salen = res->ai_addrlen;
+
+ freeaddrinfo(res);
+ return 0;
+}
+
+#endif